Skip to content
This repository has been archived by the owner on Jan 10, 2024. It is now read-only.

Commit

Permalink
Adds support for grouping deployment nodes, infrastructure nodes, sof…
Browse files Browse the repository at this point in the history
…tware system instances, and container instances.
  • Loading branch information
simonbrowndotje committed Mar 30, 2023
1 parent d08c741 commit f657afc
Show file tree
Hide file tree
Showing 11 changed files with 131 additions and 24 deletions.
2 changes: 1 addition & 1 deletion build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ repositories {
}

dependencies {
api 'com.structurizr:structurizr-client:1.23.2'
api 'com.structurizr:structurizr-client:1.24.0'
api 'com.structurizr:structurizr-import:1.4.1'

testImplementation 'org.codehaus.groovy:groovy-jsr223:3.0.16'
Expand Down
1 change: 1 addition & 0 deletions docs/changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
- Adds support for splitting lines in the DSL source with a backslash character (https://github.com/structurizr/dsl/issues/137).
- Fixes https://github.com/structurizr/dsl/issues/114 (Parallel sequence behavior in dynamic views).
- Fixes https://github.com/structurizr/dsl/issues/239 (File context for included files varies based upon how they are included).
- Adds support for grouping deployment nodes, infrastructure nodes, software system instances, and container instances.

## 1.29.1 (17th March 2023)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,11 @@ ContainerInstance parse(DeploymentNodeDslContext context, Tokens tokens) {
containerInstance.addTags(tags.split(","));
}

if (context.hasGroup()) {
containerInstance.setGroup(context.getGroup().getName());
context.getGroup().addElement(containerInstance);
}

return containerInstance;
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,16 @@
package com.structurizr.dsl;

final class DeploymentEnvironmentDslContext extends DslContext {
final class DeploymentEnvironmentDslContext extends GroupableDslContext {

private String environment;
private final String environment;

DeploymentEnvironmentDslContext(String environment) {
super(null);
this.environment = environment;
}

DeploymentEnvironmentDslContext(String environment, ElementGroup group) {
super(group);
this.environment = environment;
}

Expand All @@ -15,6 +21,7 @@ String getEnvironment() {
@Override
protected String[] getPermittedTokens() {
return new String[] {
StructurizrDslTokens.GROUP_TOKEN,
StructurizrDslTokens.DEPLOYMENT_GROUP_TOKEN,
StructurizrDslTokens.DEPLOYMENT_NODE_TOKEN,
StructurizrDslTokens.RELATIONSHIP_TOKEN
Expand Down
17 changes: 15 additions & 2 deletions src/main/java/com/structurizr/dsl/DeploymentNodeDslContext.java
Original file line number Diff line number Diff line change
@@ -1,13 +1,20 @@
package com.structurizr.dsl;

import com.structurizr.model.DeploymentNode;
import com.structurizr.model.GroupableElement;
import com.structurizr.model.ModelItem;

final class DeploymentNodeDslContext extends ModelItemDslContext {
final class DeploymentNodeDslContext extends GroupableElementDslContext {

private DeploymentNode deploymentNode;
private final DeploymentNode deploymentNode;

DeploymentNodeDslContext(DeploymentNode deploymentNode) {
this(deploymentNode, null);
}

public DeploymentNodeDslContext(DeploymentNode deploymentNode, ElementGroup group) {
super(group);

this.deploymentNode = deploymentNode;
}

Expand All @@ -20,9 +27,15 @@ ModelItem getModelItem() {
return getDeploymentNode();
}

@Override
GroupableElement getElement() {
return deploymentNode;
}

@Override
protected String[] getPermittedTokens() {
return new String[] {
StructurizrDslTokens.GROUP_TOKEN,
StructurizrDslTokens.DEPLOYMENT_NODE_TOKEN,
StructurizrDslTokens.INFRASTRUCTURE_NODE_TOKEN,
StructurizrDslTokens.SOFTWARE_SYSTEM_INSTANCE_TOKEN,
Expand Down
61 changes: 53 additions & 8 deletions src/main/java/com/structurizr/dsl/DeploymentNodeParser.java
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ final class DeploymentNodeParser extends AbstractParser {
private static final int TAGS_INDEX = 4;
private static final int INSTANCES_INDEX = 5;

DeploymentNode parse(DslContext context, Tokens tokens) {
DeploymentNode parse(DeploymentEnvironmentDslContext context, Tokens tokens) {
// deploymentNode <name> [description] [technology] [tags] [instances]

if (tokens.hasMoreThan(INSTANCES_INDEX)) {
Expand All @@ -36,15 +36,55 @@ DeploymentNode parse(DslContext context, Tokens tokens) {
technology = tokens.get(TECHNOLOGY_INDEX);
}

if (context instanceof DeploymentEnvironmentDslContext) {
deploymentNode = context.getWorkspace().getModel().addDeploymentNode(((DeploymentEnvironmentDslContext)context).getEnvironment(), name, description, technology);
} else if (context instanceof DeploymentNodeDslContext) {
DeploymentNode parent = ((DeploymentNodeDslContext)context).getDeploymentNode();
deploymentNode = parent.addDeploymentNode(name, description, technology);
} else {
throw new RuntimeException("Unexpected deployment node");
deploymentNode = context.getWorkspace().getModel().addDeploymentNode(context.getEnvironment(), name, description, technology);

String tags = "";
if (tokens.includes(TAGS_INDEX)) {
tags = tokens.get(TAGS_INDEX);
deploymentNode.addTags(tags.split(","));
}

String instances = "1";
if (tokens.includes(INSTANCES_INDEX)) {
instances = tokens.get(INSTANCES_INDEX);
deploymentNode.setInstances(instances);
}

if (context.hasGroup()) {
deploymentNode.setGroup(context.getGroup().getName());
context.getGroup().addElement(deploymentNode);
}

return deploymentNode;
}

DeploymentNode parse(DeploymentNodeDslContext context, Tokens tokens) {
// deploymentNode <name> [description] [technology] [tags] [instances]

if (tokens.hasMoreThan(INSTANCES_INDEX)) {
throw new RuntimeException("Too many tokens, expected: " + GRAMMAR);
}

if (!tokens.includes(NAME_INDEX)) {
throw new RuntimeException("Expected: " + GRAMMAR);
}

DeploymentNode deploymentNode = null;
String name = tokens.get(NAME_INDEX);

String description = "";
if (tokens.includes(DESCRIPTION_INDEX)) {
description = tokens.get(DESCRIPTION_INDEX);
}

String technology = "";
if (tokens.includes(TECHNOLOGY_INDEX)) {
technology = tokens.get(TECHNOLOGY_INDEX);
}

DeploymentNode parent = context.getDeploymentNode();
deploymentNode = parent.addDeploymentNode(name, description, technology);

String tags = "";
if (tokens.includes(TAGS_INDEX)) {
tags = tokens.get(TAGS_INDEX);
Expand All @@ -57,6 +97,11 @@ DeploymentNode parse(DslContext context, Tokens tokens) {
deploymentNode.setInstances(instances);
}

if (context.hasGroup()) {
deploymentNode.setGroup(context.getGroup().getName());
context.getGroup().addElement(deploymentNode);
}

return deploymentNode;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,11 @@ InfrastructureNode parse(DeploymentNodeDslContext context, Tokens tokens) {
infrastructureNode.addTags(tags.split(","));
}

if (context.hasGroup()) {
infrastructureNode.setGroup(context.getGroup().getName());
context.getGroup().addElement(infrastructureNode);
}

return infrastructureNode;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,11 @@ SoftwareSystemInstance parse(DeploymentNodeDslContext context, Tokens tokens) {
softwareSystemInstance.addTags(tags.split(","));
}

if (context.hasGroup()) {
softwareSystemInstance.setGroup(context.getGroup().getName());
context.getGroup().addElement(softwareSystemInstance);
}

return softwareSystemInstance;
}

Expand Down
24 changes: 22 additions & 2 deletions src/main/java/com/structurizr/dsl/StructurizrDslParser.java
Original file line number Diff line number Diff line change
Expand Up @@ -378,6 +378,18 @@ void parse(List<String> lines, File dslFile) throws StructurizrDslParserExceptio
group.setParent(container);
startContext(new ContainerDslContext(container, group));
registerIdentifier(identifier, group);
} else if (GROUP_TOKEN.equalsIgnoreCase(firstToken) && inContext(DeploymentEnvironmentDslContext.class)) {
ElementGroup group = new GroupParser().parse(getContext(DeploymentEnvironmentDslContext.class), tokens.withoutContextStartToken());

String environment = getContext(DeploymentEnvironmentDslContext.class).getEnvironment();
startContext(new DeploymentEnvironmentDslContext(environment, group));
registerIdentifier(identifier, group);
} else if (GROUP_TOKEN.equalsIgnoreCase(firstToken) && inContext(DeploymentNodeDslContext.class)) {
ElementGroup group = new GroupParser().parse(getContext(DeploymentNodeDslContext.class), tokens.withoutContextStartToken());

DeploymentNode deploymentNode = getContext(DeploymentNodeDslContext.class).getDeploymentNode();
startContext(new DeploymentNodeDslContext(deploymentNode, group));
registerIdentifier(identifier, group);
} else if (TAGS_TOKEN.equalsIgnoreCase(firstToken) && inContext(ModelItemDslContext.class) && !getContext(ModelItemDslContext.class).hasGroup()) {
new ModelItemParser().parseTags(getContext(ModelItemDslContext.class), tokens);

Expand Down Expand Up @@ -575,8 +587,16 @@ void parse(List<String> lines, File dslFile) throws StructurizrDslParserExceptio

registerIdentifier(identifier, new DeploymentGroup(group));

} else if (DEPLOYMENT_NODE_TOKEN.equalsIgnoreCase(firstToken) && (inContext(DeploymentEnvironmentDslContext.class) || inContext(DeploymentNodeDslContext.class))) {
DeploymentNode deploymentNode = new DeploymentNodeParser().parse(getContext(), tokens.withoutContextStartToken());
} else if (DEPLOYMENT_NODE_TOKEN.equalsIgnoreCase(firstToken) && inContext(DeploymentEnvironmentDslContext.class)) {
DeploymentNode deploymentNode = new DeploymentNodeParser().parse(getContext(DeploymentEnvironmentDslContext.class), tokens.withoutContextStartToken());

if (shouldStartContext(tokens)) {
startContext(new DeploymentNodeDslContext(deploymentNode));
}

registerIdentifier(identifier, deploymentNode);
} else if (DEPLOYMENT_NODE_TOKEN.equalsIgnoreCase(firstToken) && inContext(DeploymentNodeDslContext.class)) {
DeploymentNode deploymentNode = new DeploymentNodeParser().parse(getContext(DeploymentNodeDslContext.class), tokens.withoutContextStartToken());

if (shouldStartContext(tokens)) {
startContext(new DeploymentNodeDslContext(deploymentNode));
Expand Down
20 changes: 13 additions & 7 deletions src/test/dsl/groups.dsl
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,19 @@ workspace {
}

live = deploymentEnvironment "Live" {
deploymentNode "Server 1" {
containerInstance service1Api
containerInstance service1Database
}
deploymentNode "Server 2" {
containerInstance service2Api
containerInstance service2Database
group "Servers" {
deploymentNode "Server 1" {
group "Service 1" {
containerInstance service1Api
containerInstance service1Database
}
}
deploymentNode "Server 2" {
group "Service 2" {
containerInstance service2Api
containerInstance service2Database
}
}
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ class DeploymentNodeParserTests extends AbstractTests {
@Test
void test_parse_ThrowsAnException_WhenThereAreTooManyTokens() {
try {
parser.parse(context(), tokens("deploymentNode", "name", "description", "technology", "tags", "instances", "extra"));
parser.parse(new DeploymentEnvironmentDslContext("env"), tokens("deploymentNode", "name", "description", "technology", "tags", "instances", "extra"));
fail();
} catch (Exception e) {
assertEquals("Too many tokens, expected: deploymentNode <name> [description] [technology] [tags] [instances] {", e.getMessage());
Expand All @@ -23,7 +23,7 @@ void test_parse_ThrowsAnException_WhenThereAreTooManyTokens() {
@Test
void test_parse_ThrowsAnException_WhenTheNameIsNotSpecified() {
try {
parser.parse(context(), tokens("deploymentNode"));
parser.parse(new DeploymentEnvironmentDslContext("env"), tokens("deploymentNode"));
fail();
} catch (Exception e) {
assertEquals("Expected: deploymentNode <name> [description] [technology] [tags] [instances] {", e.getMessage());
Expand Down

0 comments on commit f657afc

Please sign in to comment.