public void Test_Name_WithASoftwareSystemAndNoEnvironment()
        {
            SoftwareSystem softwareSystem = Model.AddSoftwareSystem("Software System", "");

            deploymentView = Views.CreateDeploymentView(softwareSystem, "deployment", "Description");
            Assert.Equal("Software System - Deployment", deploymentView.Name);
        }
        public void Test_AddAnimationStep_ThrowsAnException_WhenContainerInstancesAreSpecifiedButNoneOfThemExistInTheView()
        {
            try
            {
                SoftwareSystem softwareSystem = Model.AddSoftwareSystem("Software System", "");
                Container      webApplication = softwareSystem.AddContainer("Web Application", "Description", "Technology");
                Container      database       = softwareSystem.AddContainer("Database", "Description", "Technology");
                webApplication.Uses(database, "Reads from and writes to", "JDBC/HTTPS");

                DeploymentNode    developerLaptop        = Model.AddDeploymentNode("Developer Laptop", "Description", "Technology");
                DeploymentNode    apacheTomcat           = developerLaptop.AddDeploymentNode("Apache Tomcat", "Description", "Technology");
                DeploymentNode    oracle                 = developerLaptop.AddDeploymentNode("Oracle", "Description", "Technology");
                ContainerInstance webApplicationInstance = apacheTomcat.Add(webApplication);
                ContainerInstance databaseInstance       = oracle.Add(database);

                deploymentView = Views.CreateDeploymentView(softwareSystem, "deployment", "Description");

                deploymentView.AddAnimation(webApplicationInstance, databaseInstance);
                throw new TestFailedException();
            }
            catch (ArgumentException ae)
            {
                Assert.Equal("None of the specified container instances exist in this view.", ae.Message);
            }
        }
        public void Test_AddAnimationStep_IgnoresContainerInstancesThatDoNotExistInTheView()
        {
            SoftwareSystem softwareSystem = Model.AddSoftwareSystem("Software System", "");
            Container      webApplication = softwareSystem.AddContainer("Web Application", "Description", "Technology");
            Container      database       = softwareSystem.AddContainer("Database", "Description", "Technology");

            webApplication.Uses(database, "Reads from and writes to", "JDBC/HTTPS");

            DeploymentNode    developerLaptop        = Model.AddDeploymentNode("Developer Laptop", "Description", "Technology");
            DeploymentNode    apacheTomcat           = developerLaptop.AddDeploymentNode("Apache Tomcat", "Description", "Technology");
            DeploymentNode    oracle                 = developerLaptop.AddDeploymentNode("Oracle", "Description", "Technology");
            ContainerInstance webApplicationInstance = apacheTomcat.Add(webApplication);
            ContainerInstance databaseInstance       = oracle.Add(database);

            deploymentView = Views.CreateDeploymentView(softwareSystem, "deployment", "Description");
            deploymentView.Add(apacheTomcat);

            deploymentView.AddAnimation(webApplicationInstance, databaseInstance);

            Animation step1 = deploymentView.Animations.First(step => step.Order == 1);

            Assert.Equal(3, step1.Elements.Count);
            Assert.True(step1.Elements.Contains(developerLaptop.Id));
            Assert.True(step1.Elements.Contains(apacheTomcat.Id));
            Assert.True(step1.Elements.Contains(webApplicationInstance.Id));
            Assert.Equal(0, step1.Relationships.Count);
        }
        public void Write(DeploymentView view, TextWriter writer)
        {
            if (view == null)
            {
                throw new ArgumentException("A deployment view must be specified.");
            }

            try
            {
                WriteHeader(view, writer);

                view.Elements
                .Where(ev => ev.Element is DeploymentNode && ev.Element.Parent == null)
                .Select(ev => ev.Element as DeploymentNode)
                .OrderBy(e => e.Name).ToList()
                .ForEach(e => Write(e, writer, 0));

                Write(view.Relationships, writer);

                WriteFooter(writer);
            }
            catch (IOException e)
            {
                Console.WriteLine(e.StackTrace);
            }
        }
        public void Test_AddAllDeploymentNodes_DoesNothing_WhenThereAreNoTopLevelDeploymentNodes()
        {
            deploymentView = Views.CreateDeploymentView("deployment", "Description");

            deploymentView.AddAllDeploymentNodes();
            Assert.Equal(0, deploymentView.Elements.Count);
        }
        public void test_writeDeploymentView()
        {
            PopulateWorkspace();

            DeploymentView deploymentView = _workspace.Views.DeploymentViews.First();

            _plantUMLWriter.Write(deploymentView, _stringWriter);

            Assert.Equal(
                @"@startuml
title Software System - Deployment
node ""Database Server"" <<Ubuntu 12.04 LTS>> as 23 {
  node ""MySQL"" <<MySQL 5.5.x>> as 24 {
    artifact ""Database"" <<Container>> as 25
  }
}
node ""Web Server"" <<Ubuntu 12.04 LTS>> as 20 {
  node ""Apache Tomcat"" <<Apache Tomcat 8.x>> as 21 {
    artifact ""Web Application"" <<Container>> as 22
  }
}
22 ..> 25 : Reads from and writes to <<JDBC>>
@enduml

".UnifyNewLine(), _stringWriter.ToString());
        }
        public void Test_AddAllDeploymentNodes_DoesNothing_WhenThereAreTopLevelDeploymentNodesButNoContainerInstances()
        {
            deploymentView = Views.CreateDeploymentView("deployment", "Description");
            Model.AddDeploymentNode("Deployment Node", "Description", "Technology");

            deploymentView.AddAllDeploymentNodes();
            Assert.Equal(0, deploymentView.Elements.Count);
        }
        public void Test_AddAllDeploymentNodes_DoesNothing_WhenThereNoDeploymentNodesForTheDeploymentEnvironment()
        {
            SoftwareSystem    softwareSystem    = Model.AddSoftwareSystem("Software System", "");
            Container         container         = softwareSystem.AddContainer("Container", "Description", "Technology");
            DeploymentNode    deploymentNode    = Model.AddDeploymentNode("Deployment Node", "Description", "Technology");
            ContainerInstance containerInstance = deploymentNode.Add(container);

            deploymentView             = Views.CreateDeploymentView(softwareSystem, "deployment", "Description");
            deploymentView.Environment = "Live";
            deploymentView.AddAllDeploymentNodes();
            Assert.Equal(0, deploymentView.Elements.Count);
        }
        public void Test_AddAllDeploymentNodes_AddsDeploymentNodesAndContainerInstances_WhenThereAreTopLevelDeploymentNodesWithContainerInstances()
        {
            SoftwareSystem    softwareSystem    = Model.AddSoftwareSystem("Software System", "");
            Container         container         = softwareSystem.AddContainer("Container", "Description", "Technology");
            DeploymentNode    deploymentNode    = Model.AddDeploymentNode("Deployment Node", "Description", "Technology");
            ContainerInstance containerInstance = deploymentNode.Add(container);

            deploymentView = Views.CreateDeploymentView(softwareSystem, "deployment", "Description");
            deploymentView.AddAllDeploymentNodes();
            Assert.Equal(2, deploymentView.Elements.Count);
            Assert.True(deploymentView.Elements.Contains(new ElementView(deploymentNode)));
            Assert.True(deploymentView.Elements.Contains(new ElementView(containerInstance)));
        }
 public void Test_AddRelationship_ThrowsAnException_WhenPassedNull()
 {
     try
     {
         deploymentView = Views.CreateDeploymentView("key", "Description");
         deploymentView.Add((Relationship)null);
         throw new TestFailedException();
     }
     catch (ArgumentException ae)
     {
         Assert.Equal("A relationship must be specified.", ae.Message);
     }
 }
 public void Test_AddAnimationStep_ThrowsAnException_WhenNoContainerInstancesOrInfrastructureNodesAreSpecified()
 {
     try
     {
         deploymentView = Views.CreateDeploymentView("deployment", "Description");
         deploymentView.AddAnimation((ContainerInstance[])null, (InfrastructureNode[])null);
         throw new TestFailedException();
     }
     catch (ArgumentException ae)
     {
         Assert.Equal("One or more container instances/infrastructure nodes must be specified.", ae.Message);
     }
 }
Beispiel #12
0
        protected override void Write(DeploymentView view, TextWriter writer)
        {
            WriteProlog(view, writer);

            view.Elements
            .Where(ev => ev.Element is DeploymentNode && ev.Element.Parent == null)
            .Select(ev => ev.Element as DeploymentNode)
            .OrderBy(e => e.Name).ToList()
            .ForEach(e => Write(e, writer, 0));

            Write(view.Relationships, writer);

            WriteEpilog(view, writer);
        }
Beispiel #13
0
        public void Test_Add_AddsTheInfrastructureNode()
        {
            DeploymentNode     deploymentNodeParent = Model.AddDeploymentNode("Deployment Node", "Description", "Technology");
            DeploymentNode     deploymentNodeChild  = deploymentNodeParent.AddDeploymentNode("Deployment Node", "Description", "Technology");
            InfrastructureNode infrastructureNode1  = deploymentNodeChild.AddInfrastructureNode("Infrastructure Node 1");
            InfrastructureNode infrastructureNode2  = deploymentNodeChild.AddInfrastructureNode("Infrastructure Node 2");

            deploymentView = Views.CreateDeploymentView("deployment", "Description");
            deploymentView.Add(infrastructureNode1);

            Assert.Equal(3, deploymentView.Elements.Count);
            Assert.True(deploymentView.Elements.Contains(new ElementView(deploymentNodeParent)));
            Assert.True(deploymentView.Elements.Contains(new ElementView(deploymentNodeChild)));
            Assert.True(deploymentView.Elements.Contains(new ElementView(infrastructureNode1)));
        }
        public void Test_AddDeploymentNode_AddsTheParentToo()
        {
            SoftwareSystem    softwareSystem       = Model.AddSoftwareSystem("Software System", "");
            Container         container            = softwareSystem.AddContainer("Container", "Description", "Technology");
            DeploymentNode    deploymentNodeParent = Model.AddDeploymentNode("Deployment Node", "Description", "Technology");
            DeploymentNode    deploymentNodeChild  = deploymentNodeParent.AddDeploymentNode("Deployment Node", "Description", "Technology");
            ContainerInstance containerInstance    = deploymentNodeChild.Add(container);

            deploymentView = Views.CreateDeploymentView(softwareSystem, "deployment", "Description");
            deploymentView.Add(deploymentNodeChild);
            Assert.Equal(3, deploymentView.Elements.Count);
            Assert.True(deploymentView.Elements.Contains(new ElementView(deploymentNodeParent)));
            Assert.True(deploymentView.Elements.Contains(new ElementView(deploymentNodeChild)));
            Assert.True(deploymentView.Elements.Contains(new ElementView(containerInstance)));
        }
Beispiel #15
0
        public void Test_Add_AddsTheSoftwareSystemInstance()
        {
            SoftwareSystem         softwareSystem         = Model.AddSoftwareSystem("Software System");
            DeploymentNode         deploymentNodeParent   = Model.AddDeploymentNode("Deployment Node", "Description", "Technology");
            DeploymentNode         deploymentNodeChild    = deploymentNodeParent.AddDeploymentNode("Deployment Node", "Description", "Technology");
            InfrastructureNode     infrastructureNode     = deploymentNodeChild.AddInfrastructureNode("Infrastructure Node ");
            SoftwareSystemInstance softwareSystemInstance = deploymentNodeChild.Add(softwareSystem);

            deploymentView = Views.CreateDeploymentView("deployment", "Description");
            deploymentView.Add(softwareSystemInstance);

            Assert.Equal(3, deploymentView.Elements.Count);
            Assert.True(deploymentView.Elements.Contains(new ElementView(deploymentNodeParent)));
            Assert.True(deploymentView.Elements.Contains(new ElementView(deploymentNodeChild)));
            Assert.True(deploymentView.Elements.Contains(new ElementView(softwareSystemInstance)));
        }
        public void Test_Remove_RemovesTheChildDeploymentNodeAndChildren()
        {
            SoftwareSystem     softwareSystem       = Model.AddSoftwareSystem("Software System", "");
            Container          container            = softwareSystem.AddContainer("Container", "Description", "Technology");
            DeploymentNode     deploymentNodeParent = Model.AddDeploymentNode("Deployment Node", "Description", "Technology");
            DeploymentNode     deploymentNodeChild  = deploymentNodeParent.AddDeploymentNode("Deployment Node", "Description", "Technology");
            InfrastructureNode infrastructureNode   = deploymentNodeChild.AddInfrastructureNode("Infrastructure Node");
            ContainerInstance  containerInstance    = deploymentNodeChild.Add(container);

            deploymentView = Views.CreateDeploymentView(softwareSystem, "deployment", "Description");
            deploymentView.AddAllDeploymentNodes();
            Assert.Equal(4, deploymentView.Elements.Count);

            deploymentView.Remove(deploymentNodeParent);
            Assert.Equal(0, deploymentView.Elements.Count);
        }
Beispiel #17
0
        static void Main()
        {
            Workspace workspace = new Workspace("HTTP-based health checks example", "An example of how to use the HTTP-based health checks feature");
            Model     model     = workspace.Model;
            ViewSet   views     = workspace.Views;

            SoftwareSystem structurizr    = model.AddSoftwareSystem("Structurizr", "A publishing platform for software architecture diagrams and documentation based upon the C4 model.");
            Container      webApplication = structurizr.AddContainer("structurizr.com", "Provides all of the server-side functionality of Structurizr, serving static and dynamic content to users.", "Java and Spring MVC");
            Container      database       = structurizr.AddContainer("Database", "Stores information about users, workspaces, etc.", "Relational Database Schema");

            database.AddTags(DatabaseTag);
            webApplication.Uses(database, "Reads from and writes to", "JDBC");

            DeploymentNode    amazonWebServices  = model.AddDeploymentNode("Amazon Web Services", "", "us-east-1");
            DeploymentNode    pivotalWebServices = amazonWebServices.AddDeploymentNode("Pivotal Web Services", "Platform as a Service provider.", "Cloud Foundry");
            ContainerInstance liveWebApplication = pivotalWebServices.AddDeploymentNode("www.structurizr.com", "An open source Java EE web server.", "Apache Tomcat")
                                                   .Add(webApplication);
            ContainerInstance liveDatabaseInstance = amazonWebServices.AddDeploymentNode("Amazon RDS", "Database as a Service provider.", "MySQL")
                                                     .Add(database);

            // add health checks to the container instances, which return a simple HTTP 200 to say everything is okay
            liveWebApplication.AddHealthCheck("Web Application is running", "https://www.structurizr.com/health");
            liveDatabaseInstance.AddHealthCheck("Database is accessible from Web Application", "https://www.structurizr.com/health/database");

            // the pass/fail status from the health checks is used to supplement any deployment views that include the container instances that have health checks defined
            DeploymentView deploymentView = views.CreateDeploymentView(structurizr, "Deployment", "A deployment diagram showing the live environment.");

            deploymentView.Environment = "Live";
            deploymentView.AddAllDeploymentNodes();

            views.Configuration.Styles.Add(new ElementStyle(Tags.Element)
            {
                Color = "#ffffff"
            });
            views.Configuration.Styles.Add(new ElementStyle(DatabaseTag)
            {
                Shape = Shape.Cylinder
            });

            StructurizrClient structurizrClient = new StructurizrClient(ApiKey, ApiSecret);

            WorkspaceUtils.PrintWorkspaceAsJson(workspace);
            Console.ReadKey();
            structurizrClient.PutWorkspaceAsync(WorkspaceId, workspace).Wait();
        }
Beispiel #18
0
        public void Test_AddContainerInstance_ThrowsAnException_WhenTheParentSoftwareSystemInstanceHasAlreadyBeenAdded()
        {
            SoftwareSystem         softwareSystem         = Model.AddSoftwareSystem("Software System");
            Container              container              = softwareSystem.AddContainer("Container");
            DeploymentNode         deploymentNodeParent   = Model.AddDeploymentNode("Deployment Node", "Description", "Technology");
            DeploymentNode         deploymentNodeChild    = deploymentNodeParent.AddDeploymentNode("Deployment Node", "Description", "Technology");
            SoftwareSystemInstance softwareSystemInstance = deploymentNodeChild.Add(softwareSystem);
            ContainerInstance      containerInstance      = deploymentNodeChild.Add(container);

            deploymentView = Views.CreateDeploymentView("deployment", "Description");
            deploymentView.Add(softwareSystemInstance);

            try
            {
                deploymentView.Add(containerInstance);
                throw new TestFailedException();
            }
            catch (ElementNotPermittedInViewException e)
            {
                Assert.Equal("The parent of Container is already in this view.", e.Message);
            }
        }
        public void Test_AddAllDeploymentNodes_AddsDeploymentNodesAndContainerInstancesOnlyForTheSoftwareSystemInScope()
        {
            SoftwareSystem    softwareSystem1    = Model.AddSoftwareSystem("Software System 1", "");
            Container         container1         = softwareSystem1.AddContainer("Container 1", "Description", "Technology");
            DeploymentNode    deploymentNode1    = Model.AddDeploymentNode("Deployment Node 1", "Description", "Technology");
            ContainerInstance containerInstance1 = deploymentNode1.Add(container1);

            SoftwareSystem    softwareSystem2    = Model.AddSoftwareSystem("Software System 2", "");
            Container         container2         = softwareSystem2.AddContainer("Container 2", "Description", "Technology");
            DeploymentNode    deploymentNode2    = Model.AddDeploymentNode("Deployment Node 2", "Description", "Technology");
            ContainerInstance containerInstance2 = deploymentNode2.Add(container2);

            // two containers from different software systems on the same deployment node
            deploymentNode1.Add(container2);

            deploymentView = Views.CreateDeploymentView(softwareSystem1, "deployment", "Description");
            deploymentView.AddAllDeploymentNodes();

            Assert.Equal(2, deploymentView.Elements.Count);
            Assert.True(deploymentView.Elements.Contains(new ElementView(deploymentNode1)));
            Assert.True(deploymentView.Elements.Contains(new ElementView(containerInstance1)));
        }
Beispiel #20
0
        public void test_writeDeploymentView()
        {
            PopulateWorkspace();

            DeploymentView deploymentView = _workspace.Views.DeploymentViews.First();

            _plantUMLWriter.Write(deploymentView, _stringWriter);

            Assert.Equal("@startuml" + Environment.NewLine +
                         "title Software System - Deployment" + Environment.NewLine +
                         "node \"Database Server\" <<Ubuntu 12.04 LTS>> as 23 {" + Environment.NewLine +
                         "  node \"MySQL\" <<MySQL 5.5.x>> as 24 {" + Environment.NewLine +
                         "    artifact \"Database\" <<Container>> as 25" + Environment.NewLine +
                         "  }" + Environment.NewLine +
                         "}" + Environment.NewLine +
                         "node \"Web Server\" <<Ubuntu 12.04 LTS>> as 20 {" + Environment.NewLine +
                         "  node \"Apache Tomcat\" <<Apache Tomcat 8.x>> as 21 {" + Environment.NewLine +
                         "    artifact \"Web Application\" <<Container>> as 22" + Environment.NewLine +
                         "  }" + Environment.NewLine +
                         "}" + Environment.NewLine +
                         "22 ..> 25 : Reads from and writes to <<JDBC>>" + Environment.NewLine +
                         "@enduml" + Environment.NewLine +
                         Environment.NewLine, _stringWriter.ToString());
        }
Beispiel #21
0
        private void PopulateWorkspace()
        {
            Model   model = _workspace.Model;
            ViewSet views = _workspace.Views;

            model.Enterprise = new Enterprise("Some Enterprise");

            Person         user           = model.AddPerson(Location.Internal, "User", "");
            SoftwareSystem softwareSystem = model.AddSoftwareSystem(Location.Internal, "Software System", "");

            user.Uses(softwareSystem, "Uses");

            SoftwareSystem emailSystem = model.AddSoftwareSystem(Location.External, "E-mail System", "");

            softwareSystem.Uses(emailSystem, "Sends e-mail using");
            emailSystem.Delivers(user, "Delivers e-mails to");

            Container webApplication = softwareSystem.AddContainer("Web Application", "", "");
            Container database       = softwareSystem.AddContainer("Database", "", "");

            user.Uses(webApplication, "Uses", "HTTP");
            webApplication.Uses(database, "Reads from and writes to", "JDBC");
            webApplication.Uses(emailSystem, "Sends e-mail using");

            Component controller     = webApplication.AddComponent("SomeController", "", "Spring MVC Controller");
            Component emailComponent = webApplication.AddComponent("EmailComponent", "");
            Component repository     = webApplication.AddComponent("SomeRepository", "", "Spring Data");

            user.Uses(controller, "Uses", "HTTP");
            controller.Uses(repository, "Uses");
            controller.Uses(emailComponent, "Sends e-mail using");
            repository.Uses(database, "Reads from and writes to", "JDBC");
            emailComponent.Uses(emailSystem, "Sends e-mails using", "SMTP");

            DeploymentNode webServer = model.AddDeploymentNode("Web Server", "A server hosted at AWS EC2.", "Ubuntu 12.04 LTS");

            webServer.AddDeploymentNode("Apache Tomcat", "The live web server", "Apache Tomcat 8.x")
            .Add(webApplication);
            DeploymentNode databaseServer = model.AddDeploymentNode("Database Server", "A server hosted at AWS EC2.", "Ubuntu 12.04 LTS");

            databaseServer.AddDeploymentNode("MySQL", "The live database server", "MySQL 5.5.x")
            .Add(database);

            EnterpriseContextView
                enterpriseContextView = views.CreateEnterpriseContextView("enterpriseContext", "");

            enterpriseContextView.AddAllElements();

            SystemContextView systemContextView = views.CreateSystemContextView(softwareSystem, "systemContext", "");

            systemContextView.AddAllElements();

            ContainerView containerView = views.CreateContainerView(softwareSystem, "containers", "");

            containerView.AddAllElements();

            ComponentView componentView = views.CreateComponentView(webApplication, "components", "");

            componentView.AddAllElements();

            DynamicView dynamicView = views.CreateDynamicView(webApplication, "dynamic", "");

            dynamicView.Add(user, "Requests /something", controller);
            dynamicView.Add(controller, repository);
            dynamicView.Add(repository, "select * from something", database);

            DeploymentView deploymentView = views.CreateDeploymentView(softwareSystem, "deployment", "");

            deploymentView.AddAllDeploymentNodes();
        }
        public static Workspace Create()
        {
            Workspace workspace = new Workspace("Big Bank plc", "This is an example workspace to illustrate the key features of Structurizr, based around a fictional online banking system.");
            Model     model     = workspace.Model;
            ViewSet   views     = workspace.Views;

            model.Enterprise = new Enterprise("Big Bank plc");

            // people and software systems
            Person customer = model.AddPerson(Location.External, "Personal Banking Customer", "A customer of the bank, with personal bank accounts.");

            SoftwareSystem internetBankingSystem = model.AddSoftwareSystem(Location.Internal, "Internet Banking System", "Allows customers to view information about their bank accounts, and make payments.");

            customer.Uses(internetBankingSystem, "Uses");

            SoftwareSystem mainframeBankingSystem = model.AddSoftwareSystem(Location.Internal, "Mainframe Banking System", "Stores all of the core banking information about customers, accounts, transactions, etc.");

            mainframeBankingSystem.AddTags(ExistingSystemTag);
            internetBankingSystem.Uses(mainframeBankingSystem, "Uses");

            SoftwareSystem emailSystem = model.AddSoftwareSystem(Location.Internal, "E-mail System", "The internal Microsoft Exchange e-mail system.");

            internetBankingSystem.Uses(emailSystem, "Sends e-mail using");
            emailSystem.AddTags(ExistingSystemTag);
            emailSystem.Delivers(customer, "Sends e-mails to");

            SoftwareSystem atm = model.AddSoftwareSystem(Location.Internal, "ATM", "Allows customers to withdraw cash.");

            atm.AddTags(ExistingSystemTag);
            atm.Uses(mainframeBankingSystem, "Uses");
            customer.Uses(atm, "Withdraws cash using");

            Person customerServiceStaff = model.AddPerson(Location.Internal, "Customer Service Staff", "Customer service staff within the bank.");

            customerServiceStaff.AddTags(BankStaffTag);
            customerServiceStaff.Uses(mainframeBankingSystem, "Uses");
            customer.InteractsWith(customerServiceStaff, "Asks questions to", "Telephone");

            Person backOfficeStaff = model.AddPerson(Location.Internal, "Back Office Staff", "Administration and support staff within the bank.");

            backOfficeStaff.AddTags(BankStaffTag);
            backOfficeStaff.Uses(mainframeBankingSystem, "Uses");

            // containers
            Container singlePageApplication = internetBankingSystem.AddContainer("Single-Page Application", "Provides all of the Internet banking functionality to customers via their web browser.", "JavaScript and Angular");

            singlePageApplication.AddTags(WebBrowserTag);
            Container mobileApp = internetBankingSystem.AddContainer("Mobile App", "Provides a limited subset of the Internet banking functionality to customers via their mobile device.", "Xamarin");

            mobileApp.AddTags(MobileAppTag);
            Container webApplication = internetBankingSystem.AddContainer("Web Application", "Delivers the static content and the Internet banking single page application.", "Java and Spring MVC");
            Container apiApplication = internetBankingSystem.AddContainer("API Application", "Provides Internet banking functionality via a JSON/HTTPS API.", "Java and Spring MVC");
            Container database       = internetBankingSystem.AddContainer("Database", "Stores user registration information, hashed authentication credentials, access logs, etc.", "Relational Database Schema");

            database.AddTags(DatabaseTag);

            customer.Uses(webApplication, "Uses", "HTTPS");
            customer.Uses(singlePageApplication, "Uses", "");
            customer.Uses(mobileApp, "Uses", "");
            webApplication.Uses(singlePageApplication, "Delivers to the customer's web browser", "");
            apiApplication.Uses(database, "Reads from and writes to", "JDBC");
            apiApplication.Uses(mainframeBankingSystem, "Uses", "XML/HTTPS");
            apiApplication.Uses(emailSystem, "Sends e-mail using", "SMTP");

            // components
            // - for a real-world software system, you would probably want to extract the components using
            // - static analysis/reflection rather than manually specifying them all
            Component signinController             = apiApplication.AddComponent("Sign In Controller", "Allows users to sign in to the Internet Banking System.", "Spring MVC Rest Controller");
            Component accountsSummaryController    = apiApplication.AddComponent("Accounts Summary Controller", "Provides customers with a summary of their bank accounts.", "Spring MVC Rest Controller");
            Component resetPasswordController      = apiApplication.AddComponent("Reset Password Controller", "Allows users to reset their passwords with a single use URL.", "Spring MVC Rest Controller");
            Component securityComponent            = apiApplication.AddComponent("Security Component", "Provides functionality related to signing in, changing passwords, etc.", "Spring Bean");
            Component mainframeBankingSystemFacade = apiApplication.AddComponent("Mainframe Banking System Facade", "A facade onto the mainframe banking system.", "Spring Bean");
            Component emailComponent = apiApplication.AddComponent("E-mail Component", "Sends e-mails to users.", "Spring Bean");

            apiApplication.Components.Where(c => "Spring MVC Rest Controller".Equals(c.Technology)).ToList().ForEach(c => singlePageApplication.Uses(c, "Makes API calls to", "JSON/HTTPS"));
            apiApplication.Components.Where(c => "Spring MVC Rest Controller".Equals(c.Technology)).ToList().ForEach(c => mobileApp.Uses(c, "Makes API calls to", "JSON/HTTPS"));
            signinController.Uses(securityComponent, "Uses");
            accountsSummaryController.Uses(mainframeBankingSystemFacade, "Uses");
            resetPasswordController.Uses(securityComponent, "Uses");
            resetPasswordController.Uses(emailComponent, "Uses");
            securityComponent.Uses(database, "Reads from and writes to", "JDBC");
            mainframeBankingSystemFacade.Uses(mainframeBankingSystem, "Uses", "XML/HTTPS");
            emailComponent.Uses(emailSystem, "Sends e-mail using");

            model.AddImplicitRelationships();

            // deployment nodes and container instances
            DeploymentNode developerLaptop = model.AddDeploymentNode("Development", "Developer Laptop", "A developer laptop.", "Microsoft Windows 10 or Apple macOS");
            DeploymentNode apacheTomcat    = developerLaptop.AddDeploymentNode("Docker Container - Web Server", "A Docker container.", "Docker")
                                             .AddDeploymentNode("Apache Tomcat", "An open source Java EE web server.", "Apache Tomcat 8.x", 1, DictionaryUtils.Create("Xmx=512M", "Xms=1024M", "Java Version=8"));

            apacheTomcat.Add(webApplication);
            apacheTomcat.Add(apiApplication);

            developerLaptop.AddDeploymentNode("Docker Container - Database Server", "A Docker container.", "Docker")
            .AddDeploymentNode("Database Server", "A development database.", "Oracle 12c")
            .Add(database);

            developerLaptop.AddDeploymentNode("Web Browser", "", "Chrome, Firefox, Safari, or Edge").Add(singlePageApplication);

            DeploymentNode customerMobileDevice = model.AddDeploymentNode("Live", "Customer's mobile device", "", "Apple iOS or Android");

            customerMobileDevice.Add(mobileApp);

            DeploymentNode customerComputer = model.AddDeploymentNode("Live", "Customer's computer", "", "Microsoft Windows or Apple macOS");

            customerComputer.AddDeploymentNode("Web Browser", "", "Chrome, Firefox, Safari, or Edge").Add(singlePageApplication);

            DeploymentNode bigBankDataCenter = model.AddDeploymentNode("Live", "Big Bank plc", "", "Big Bank plc data center");

            DeploymentNode liveWebServer = bigBankDataCenter.AddDeploymentNode("bigbank-web***", "A web server residing in the web server farm, accessed via F5 BIG-IP LTMs.", "Ubuntu 16.04 LTS", 4, DictionaryUtils.Create("Location=London and Reading"));

            liveWebServer.AddDeploymentNode("Apache Tomcat", "An open source Java EE web server.", "Apache Tomcat 8.x", 1, DictionaryUtils.Create("Xmx=512M", "Xms=1024M", "Java Version=8"))
            .Add(webApplication);

            DeploymentNode liveApiServer = bigBankDataCenter.AddDeploymentNode("bigbank-api***", "A web server residing in the web server farm, accessed via F5 BIG-IP LTMs.", "Ubuntu 16.04 LTS", 8, DictionaryUtils.Create("Location=London and Reading"));

            liveApiServer.AddDeploymentNode("Apache Tomcat", "An open source Java EE web server.", "Apache Tomcat 8.x", 1, DictionaryUtils.Create("Xmx=512M", "Xms=1024M", "Java Version=8"))
            .Add(apiApplication);

            DeploymentNode primaryDatabaseServer = bigBankDataCenter.AddDeploymentNode("bigbank-db01", "The primary database server.", "Ubuntu 16.04 LTS", 1, DictionaryUtils.Create("Location=London"))
                                                   .AddDeploymentNode("Oracle - Primary", "The primary, live database server.", "Oracle 12c");

            primaryDatabaseServer.Add(database);

            DeploymentNode bigBankdb02 = bigBankDataCenter.AddDeploymentNode("bigbank-db02", "The secondary database server.", "Ubuntu 16.04 LTS", 1, DictionaryUtils.Create("Location=Reading"));

            bigBankdb02.AddTags(FailoverTag);
            DeploymentNode secondaryDatabaseServer = bigBankdb02.AddDeploymentNode("Oracle - Secondary", "A secondary, standby database server, used for failover purposes only.", "Oracle 12c");

            secondaryDatabaseServer.AddTags(FailoverTag);
            ContainerInstance secondaryDatabase = secondaryDatabaseServer.Add(database);

            model.Relationships.Where(r => r.Destination.Equals(secondaryDatabase)).ToList().ForEach(r => r.AddTags(FailoverTag));
            Relationship dataReplicationRelationship = primaryDatabaseServer.Uses(secondaryDatabaseServer, "Replicates data to", "");

            secondaryDatabase.AddTags(FailoverTag);

            // views/diagrams
            SystemLandscapeView systemLandscapeView = views.CreateSystemLandscapeView("SystemLandscape", "The system landscape diagram for Big Bank plc.");

            systemLandscapeView.AddAllElements();
            systemLandscapeView.PaperSize = PaperSize.A5_Landscape;

            SystemContextView systemContextView = views.CreateSystemContextView(internetBankingSystem, "SystemContext", "The system context diagram for the Internet Banking System.");

            systemContextView.EnterpriseBoundaryVisible = false;
            systemContextView.AddNearestNeighbours(internetBankingSystem);
            systemContextView.PaperSize = PaperSize.A5_Landscape;

            ContainerView containerView = views.CreateContainerView(internetBankingSystem, "Containers", "The container diagram for the Internet Banking System.");

            containerView.Add(customer);
            containerView.AddAllContainers();
            containerView.Add(mainframeBankingSystem);
            containerView.Add(emailSystem);
            containerView.PaperSize = PaperSize.A5_Landscape;

            ComponentView componentView = views.CreateComponentView(apiApplication, "Components", "The component diagram for the API Application.");

            componentView.Add(mobileApp);
            componentView.Add(singlePageApplication);
            componentView.Add(database);
            componentView.AddAllComponents();
            componentView.Add(mainframeBankingSystem);
            componentView.Add(emailSystem);
            componentView.PaperSize = PaperSize.A5_Landscape;

            systemLandscapeView.AddAnimation(internetBankingSystem, customer, mainframeBankingSystem, emailSystem);
            systemLandscapeView.AddAnimation(atm);
            systemLandscapeView.AddAnimation(customerServiceStaff, backOfficeStaff);

            systemContextView.AddAnimation(internetBankingSystem);
            systemContextView.AddAnimation(customer);
            systemContextView.AddAnimation(mainframeBankingSystem);
            systemContextView.AddAnimation(emailSystem);

            containerView.AddAnimation(customer, mainframeBankingSystem, emailSystem);
            containerView.AddAnimation(webApplication);
            containerView.AddAnimation(singlePageApplication);
            containerView.AddAnimation(mobileApp);
            containerView.AddAnimation(apiApplication);
            containerView.AddAnimation(database);

            componentView.AddAnimation(singlePageApplication, mobileApp);
            componentView.AddAnimation(signinController, securityComponent, database);
            componentView.AddAnimation(accountsSummaryController, mainframeBankingSystemFacade, mainframeBankingSystem);
            componentView.AddAnimation(resetPasswordController, emailComponent, database);

            // dynamic diagrams and deployment diagrams are not available with the Free Plan
            DynamicView dynamicView = views.CreateDynamicView(apiApplication, "SignIn", "Summarises how the sign in feature works in the single-page application.");

            dynamicView.Add(singlePageApplication, "Submits credentials to", signinController);
            dynamicView.Add(signinController, "Calls isAuthenticated() on", securityComponent);
            dynamicView.Add(securityComponent, "select * from users where username = ?", database);
            dynamicView.PaperSize = PaperSize.A5_Landscape;

            DeploymentView developmentDeploymentView = views.CreateDeploymentView(internetBankingSystem, "DevelopmentDeployment", "An example development deployment scenario for the Internet Banking System.");

            developmentDeploymentView.Environment = "Development";
            developmentDeploymentView.Add(developerLaptop);
            developmentDeploymentView.PaperSize = PaperSize.A5_Landscape;

            DeploymentView liveDeploymentView = views.CreateDeploymentView(internetBankingSystem, "LiveDeployment", "An example live deployment scenario for the Internet Banking System.");

            liveDeploymentView.Environment = "Live";
            liveDeploymentView.Add(bigBankDataCenter);
            liveDeploymentView.Add(customerMobileDevice);
            liveDeploymentView.Add(customerComputer);
            liveDeploymentView.Add(dataReplicationRelationship);
            liveDeploymentView.PaperSize = PaperSize.A5_Landscape;

            // colours, shapes and other diagram styling
            Styles styles = views.Configuration.Styles;

            styles.Add(new ElementStyle(Tags.SoftwareSystem)
            {
                Background = "#1168bd", Color = "#ffffff"
            });
            styles.Add(new ElementStyle(Tags.Container)
            {
                Background = "#438dd5", Color = "#ffffff"
            });
            styles.Add(new ElementStyle(Tags.Component)
            {
                Background = "#85bbf0", Color = "#000000"
            });
            styles.Add(new ElementStyle(Tags.Person)
            {
                Background = "#08427b", Color = "#ffffff", Shape = Shape.Person, FontSize = 22
            });
            styles.Add(new ElementStyle(ExistingSystemTag)
            {
                Background = "#999999", Color = "#ffffff"
            });
            styles.Add(new ElementStyle(BankStaffTag)
            {
                Background = "#999999", Color = "#ffffff"
            });
            styles.Add(new ElementStyle(WebBrowserTag)
            {
                Shape = Shape.WebBrowser
            });
            styles.Add(new ElementStyle(MobileAppTag)
            {
                Shape = Shape.MobileDeviceLandscape
            });
            styles.Add(new ElementStyle(DatabaseTag)
            {
                Shape = Shape.Cylinder
            });
            styles.Add(new ElementStyle(FailoverTag)
            {
                Opacity = 25
            });
            styles.Add(new RelationshipStyle(FailoverTag)
            {
                Opacity = 25, Position = 70
            });

            // documentation
            // - usually the documentation would be included from separate Markdown/AsciiDoc files, but this is just an example
            StructurizrDocumentationTemplate template = new StructurizrDocumentationTemplate(workspace);

            template.AddContextSection(internetBankingSystem, Format.Markdown,
                                       "Here is some context about the Internet Banking System...\n" +
                                       "![](embed:SystemLandscape)\n" +
                                       "![](embed:SystemContext)\n" +
                                       "### Internet Banking System\n...\n" +
                                       "### Mainframe Banking System\n...\n");
            template.AddContainersSection(internetBankingSystem, Format.Markdown,
                                          "Here is some information about the containers within the Internet Banking System...\n" +
                                          "![](embed:Containers)\n" +
                                          "### Web Application\n...\n" +
                                          "### Database\n...\n");
            template.AddComponentsSection(webApplication, Format.Markdown,
                                          "Here is some information about the API Application...\n" +
                                          "![](embed:Components)\n" +
                                          "### Sign in process\n" +
                                          "Here is some information about the Sign In Controller, including how the sign in process works...\n" +
                                          "![](embed:SignIn)");
            template.AddDevelopmentEnvironmentSection(internetBankingSystem, Format.AsciiDoc,
                                                      "Here is some information about how to set up a development environment for the Internet Banking System...\n" +
                                                      "image::embed:DevelopmentDeployment[]");
            template.AddDeploymentSection(internetBankingSystem, Format.AsciiDoc,
                                          "Here is some information about the live deployment environment for the Internet Banking System...\n" +
                                          "image::embed:LiveDeployment[]");

            return(workspace);
        }
 /// <summary>
 /// Writes a deployment view in PlantUML format to the provided writer.
 /// </summary>
 /// <param name="view"></param>
 /// <param name="writer"></param>
 protected abstract void Write(DeploymentView view, TextWriter writer);
Beispiel #24
0
        private void BuildC4Model()
        {
            // Add stakeholders en Systemen
            SoftwareSystem boekhoudSysteem = model.AddSoftwareSystem(Location.Internal, "Boekhoudsysteem", "Boekhoudsysteem voor midden en kleinbedrijf en ZZP'er");

            SoftwareSystem itsmSysteem = model.AddSoftwareSystem(Location.Internal, "ITSM Systeem", "Interne CRM applicatie");

            itsmSysteem.AddTags(InternalSystemTag);
            boekhoudSysteem.Uses(itsmSysteem, "Haalt abonnement gegevens op");

            SoftwareSystem website = model.AddSoftwareSystem(Location.Internal, "Website", $"publieke website van {BedrijfsNaam}");

            website.AddTags(WebBrowserTag);
            website.Uses(itsmSysteem, "Registreert een abonnement");

            SoftwareSystem webshop = model.AddSoftwareSystem(Location.External, "Webshop", $"Webshopkoppeling names klant met Boekhoudsysteem");

            webshop.AddTags(ExternalSystemTag);
            boekhoudSysteem.Uses(webshop, "krijgt gegevens van");

            SoftwareSystem bank = model.AddSoftwareSystem(Location.External, "Bank", $"Bankkoppeling names klant met Boekhoudsysteem");

            bank.AddTags(ExternalSystemTag);
            boekhoudSysteem.Uses(bank, "krijgt gegevens van");

            Person hoofdgebruiker = model.AddPerson(Location.External, "Hoofdgebruiker", "De gebruiker van de klant die het abonnenement heeft afgesloten");

            hoofdgebruiker.Uses(boekhoudSysteem, Gebruikt);
            hoofdgebruiker.Uses(website, Gebruikt);

            Person gebruiker = model.AddPerson(Location.External, "Gebruiker", "De medewerker van de klant");

            gebruiker.Uses(boekhoudSysteem, Gebruikt);

            Person accountant = model.AddPerson(Location.External, "Accountant", "De accountant van de klant");

            accountant.Uses(boekhoudSysteem, Gebruikt);
            hoofdgebruiker.InteractsWith(accountant, "Vraagt controle aan bij");

            Person helpdesk = model.AddPerson(Location.Internal, "Helpdeskmedewerker", $"Helpdeskmedewerker van {BedrijfsNaam}");

            helpdesk.Uses(boekhoudSysteem, Gebruikt);
            helpdesk.Uses(itsmSysteem, Gebruikt);
            hoofdgebruiker.InteractsWith(helpdesk, "Vraagt hulp van");

            // Extra diagram: Systeemlandschap
            SystemLandscapeView systemLandscapeView = views.CreateSystemLandscapeView("SystemLandscape", "System Context diagram Boekhoudsysteem.");

            systemLandscapeView.AddAllElements();
            systemLandscapeView.EnableAutomaticLayout();

            // containers
            Container coreModule = boekhoudSysteem.AddContainer("Core Module", "Basis module voor inrichting, gebruikers", "C#");

            coreModule.AddTags(Tags.Container);
            coreModule.Uses(itsmSysteem, "krijgt gegevens van");

            Container bankModule = boekhoudSysteem.AddContainer("Bank Module", "Importeren van betaalgegevens", "C#");

            bankModule.AddTags(Tags.Container);
            bankModule.Uses(bank, "krijgt gegevens van");

            Container koppelingModule = boekhoudSysteem.AddContainer("Koppelingen Module", "Module voor inrichten diverse externe koppelingen", "C#");

            koppelingModule.AddTags(Tags.Container);
            koppelingModule.Uses(webshop, "krijgt gegevens van");

            Container boekhoudModule = boekhoudSysteem.AddContainer("Boekhoud Module", "Basis onderdelen van een Boekhoudsysteem zoals dagboeken en rapportages", "C#");

            boekhoudModule.AddTags(Tags.Container);
            boekhoudModule.Uses(webshop, "krijgt gegevens van");

            Container facturatieModule = boekhoudSysteem.AddContainer("Facturatie Module", "Facturatie en Offerte module", "C#");

            facturatieModule.AddTags(Tags.Container);
            facturatieModule.Uses(boekhoudModule, "geeft verkooporders aan");

            Container importModule = boekhoudSysteem.AddContainer("Import Module", "Module voor import en export gegevens", "C#");

            importModule.AddTags(Tags.Container);
            importModule.Uses(boekhoudModule, "geeft relaties aan");
            importModule.Uses(facturatieModule, "geeft artikelen aan");

            hoofdgebruiker.Uses(coreModule, Gebruikt);
            hoofdgebruiker.Uses(boekhoudModule, Gebruikt);
            hoofdgebruiker.Uses(facturatieModule, Gebruikt);
            hoofdgebruiker.Uses(bankModule, Gebruikt);
            hoofdgebruiker.Uses(koppelingModule, Gebruikt);
            hoofdgebruiker.Uses(importModule, Gebruikt);

            gebruiker.Uses(boekhoudModule, Gebruikt);
            gebruiker.Uses(facturatieModule, Gebruikt);
            gebruiker.Uses(bankModule, Gebruikt);

            accountant.Uses(boekhoudModule, Gebruikt);
            helpdesk.Uses(boekhoudModule, Gebruikt);

            Container databaseSystem = boekhoudSysteem.AddContainer("Systeem Database", "Opslag gebruikers, abonnement, administratie gegevens, hashed authentication credentials, access logs, etc.", "Relational Database Schema");

            databaseSystem.AddTags(DatabaseTag);
            coreModule.Uses(databaseSystem, Gebruikt);

            Container databaseAccount = boekhoudSysteem.AddContainer("Boekhouding Database", "Opslag boekhouding per abonnement per administratie", "Relational Database Schema");

            databaseAccount.AddTags(DatabaseTag);
            boekhoudModule.Uses(databaseAccount, Gebruikt);
            facturatieModule.Uses(databaseAccount, Gebruikt);
            bankModule.Uses(databaseAccount, Gebruikt);

            // Components
            Component bankImportView = bankModule.AddComponent("Bank statement Import", "Importscherm bankafschriften", "ASP.Net Webform");

            bankImportView.AddTags(WebBrowserTag);
            Component bankPaymentLogic = bankModule.AddComponent("Payment logic service", "Businesslaag bankafschriften", "C#");

            bankPaymentLogic.AddTags(InternalSystemTag);
            Component bankPaymentData = bankModule.AddComponent("Payment data service", "Datalaag bankafschriften", "C#");

            bankPaymentData.AddTags(InternalSystemTag);

            bankImportView.Uses(bankPaymentLogic, Gebruikt);
            bankPaymentLogic.Uses(bankPaymentData, Gebruikt);
            bankPaymentLogic.Uses(bank, Gebruikt);

            Component bankPaymentView = bankModule.AddComponent("Bank payments", "Betaalopdrachten", "ASP.Net Webform");

            bankPaymentView.AddTags(WebBrowserTag);
            bankPaymentView.Uses(bankPaymentLogic, Gebruikt);

            Component bankInstellingView = bankModule.AddComponent("Instellingen Bankstatements", "Instellingen bankafschriften", "ASP.Net Webform");

            bankInstellingView.AddTags(WebBrowserTag);
            Component bankInstellingLogic = bankModule.AddComponent("Bankinstellingen logic service", "Businesslaag bankinstellingen", "C#");

            bankInstellingLogic.AddTags(InternalSystemTag);
            Component bankInstellingData = bankModule.AddComponent("Bankinstellingen data service", "Datalaag bankinstellingen", "C#");

            bankInstellingData.AddTags(InternalSystemTag);

            bankInstellingView.Uses(bankInstellingLogic, Gebruikt);
            bankInstellingLogic.Uses(bankInstellingData, Gebruikt);

            bankPaymentData.Uses(databaseAccount, "Leest en schrijft naar", "Linq2Sql");
            bankInstellingData.Uses(databaseAccount, "Leest en schrijft naar", "Linq2Sql");

            Component importExportView = importModule.AddComponent("Artikel Import", "Importscherm artikelen", "ASP.Net Webform");

            importExportView.AddTags(WebBrowserTag);
            Component importExportLogic = importModule.AddComponent("Import Export logic service", "Businesslaag import export functionaliteit", "C#");

            importExportLogic.AddTags(InternalSystemTag);
            Component importExportData = importModule.AddComponent("Import Export data service", "Datalaag import export functionaliteit", "C#");

            importExportData.AddTags(InternalSystemTag);

            importExportView.Uses(importExportLogic, Gebruikt);
            importExportLogic.Uses(importExportData, Gebruikt);
            importExportData.Uses(databaseAccount, "Leest en schrijft naar", "Linq2Sql");

            // Add Views
            SystemContextView contextView = views.CreateSystemContextView(boekhoudSysteem, "SystemContext", "System Context diagram Boekhoudsysteem.");

            contextView.AddNearestNeighbours(boekhoudSysteem);
            contextView.EnableAutomaticLayout();

            ContainerView containerView = views.CreateContainerView(boekhoudSysteem, "Containers", "Het container diagram voor het boekhoudsysteem.");

            containerView.EnableAutomaticLayout();
            containerView.Add(hoofdgebruiker);
            containerView.Add(gebruiker);
            containerView.Add(accountant);
            containerView.Add(helpdesk);
            containerView.AddAllContainers();
            containerView.Add(webshop);
            containerView.Add(bank);
            containerView.Add(itsmSysteem);

            ComponentView bankComponentView = views.CreateComponentView(bankModule, "Bank Components", "Component diagram van de Bank module");

            bankComponentView.EnableAutomaticLayout();
            bankComponentView.Add(databaseAccount);
            bankComponentView.AddAllComponents();
            bankComponentView.Add(bank);

            ComponentView importExportComponentView = views.CreateComponentView(importModule, "Import-Export Components", "Component diagram van de Import Export module.");

            importExportComponentView.EnableAutomaticLayout();
            importExportComponentView.Add(databaseAccount);
            importExportComponentView.AddAllComponents();

            // Extra diagram: Deployment
            const string Productie = "Productieomgeving";

            DeploymentNode productieOmgeving = model.AddDeploymentNode(Productie, $"{BedrijfsNaam}", "", $"{BedrijfsNaam} data center");
            DeploymentNode customerComputer  = model.AddDeploymentNode(Productie, "Gebruiker's computer", "", "Microsoft Windows or Apple macOS");

            customerComputer.AddDeploymentNode("Web Browser", "", "Chrome, Firefox, Edge or IE11").Add(boekhoudModule);
            customerComputer.AddTags(WebBrowserTag);

            DeploymentNode productieWebServer = productieOmgeving.AddDeploymentNode($"{BedrijfsNaam}-web***", "Een webserver gehost in een webserver farm", "Windows 2019", 2, DictionaryUtils.Create("Location=Amsterdam"));

            productieWebServer
            .AddDeploymentNode("Microsoft IIS", "Microsoft web server.", "IIS", 1, DictionaryUtils.Create("Xmx=512M", "Xms=1024M", ".Net Framework 4.8"))
            .Add(boekhoudModule);
            customerComputer.Uses(productieWebServer, Gebruikt, "https");

            DeploymentNode primaryDatabaseServer = productieOmgeving
                                                   .AddDeploymentNode($"{BedrijfsNaam}-db01", "Primary database server.", "Windows 2019", 1, DictionaryUtils.Create("Location=Amsterdam"))
                                                   .AddDeploymentNode("SQL Server - Primary", $"Primary, {Productie} databaseserver.", "SqlServer 2017");

            primaryDatabaseServer.Add(databaseSystem);
            primaryDatabaseServer.Add(databaseAccount);

            DeploymentNode failoverDb = productieOmgeving.AddDeploymentNode($"{BedrijfsNaam}-db02", "Secondary database server.", "Windows 2019", 1, DictionaryUtils.Create("Location=Amsterdam"));

            failoverDb.AddTags(FailoverTag);

            DeploymentNode secondaryDatabaseServer = failoverDb.AddDeploymentNode("SQL Server - Secondary", "Secondary, standby database server, alleen voor failover.", "SqlServer 2017");

            secondaryDatabaseServer.AddTags(FailoverTag);

            ContainerInstance secondaryDatabaseSystem  = secondaryDatabaseServer.Add(databaseSystem);
            ContainerInstance secondaryDatabaseAccount = secondaryDatabaseServer.Add(databaseAccount);

            model.Relationships.Where(r => r.Destination.Equals(secondaryDatabaseSystem)).ToList().ForEach(r => r.AddTags(FailoverTag));
            model.Relationships.Where(r => r.Destination.Equals(secondaryDatabaseAccount)).ToList().ForEach(r => r.AddTags(FailoverTag));
            Relationship dataReplicationRelationship = primaryDatabaseServer.Uses(secondaryDatabaseServer, "Replicates data to", "");

            secondaryDatabaseSystem.AddTags(FailoverTag);
            secondaryDatabaseAccount.AddTags(FailoverTag);

            DeploymentView systeemDeploymentView = views.CreateDeploymentView(boekhoudSysteem, Productie, $"De productieomgeving van {BedrijfsNaam}.");

            //systeemDeploymentView.EnableAutomaticLayout();
            systeemDeploymentView.Environment = Productie;
            systeemDeploymentView.Add(productieOmgeving);
            systeemDeploymentView.Add(customerComputer);
            systeemDeploymentView.Add(dataReplicationRelationship);

            // Set Styling
            Styles styles = views.Configuration.Styles;

            styles.Add(new ElementStyle(Tags.SoftwareSystem)
            {
                Background = "#1168bd", Color = "#ffffff"
            });
            styles.Add(new ElementStyle(Tags.Container)
            {
                Background = "#438dd5", Color = "#ffffff"
            });
            styles.Add(new ElementStyle(Tags.Component)
            {
                Background = "#85bbf0", Color = "#000000"
            });
            styles.Add(new ElementStyle(Tags.Person)
            {
                Background = "#08427b", Color = "#ffffff", Shape = Shape.Person
            });
            styles.Add(new ElementStyle(InternalSystemTag)
            {
                Background = "#999999", Color = "#ffffff"
            });
            styles.Add(new ElementStyle(ExternalSystemTag)
            {
                Background = "#999999", Color = "#ffffff"
            });
            styles.Add(new ElementStyle(WebBrowserTag)
            {
                Shape = Shape.WebBrowser
            });
            styles.Add(new ElementStyle(DatabaseTag)
            {
                Shape = Shape.Cylinder
            });
            styles.Add(new ElementStyle(FailoverTag)
            {
                Opacity = 25
            });
            styles.Add(new RelationshipStyle(FailoverTag)
            {
                Opacity = 25, Position = 70
            });
        }
Beispiel #25
0
        private static Workspace Create(bool usePaidFeatures)
        {
            Workspace workspace = new Workspace("Big Bank plc", "This is an example workspace to illustrate the key features of Structurizr, based around a fictional online banking system.");
            Model     model     = workspace.Model;
            ViewSet   views     = workspace.Views;

            model.Enterprise = new Enterprise("Big Bank plc");

            // people and software systems
            Person customer = model.AddPerson(Location.External, "Customer", "A customer of the bank.");

            SoftwareSystem internetBankingSystem = model.AddSoftwareSystem(Location.Internal, "Internet Banking System", "Allows customers to view information about their bank accounts and make payments.");

            customer.Uses(internetBankingSystem, "Uses");

            SoftwareSystem mainframeBankingSystem = model.AddSoftwareSystem(Location.Internal, "Mainframe Banking System", "Stores all of the core banking information about customers, accounts, transactions, etc.");

            internetBankingSystem.Uses(mainframeBankingSystem, "Uses");

            SoftwareSystem atm = model.AddSoftwareSystem(Location.Internal, "ATM", "Allows customers to withdraw cash.");

            atm.Uses(mainframeBankingSystem, "Uses");
            customer.Uses(atm, "Withdraws cash using");

            Person bankStaff = model.AddPerson(Location.Internal, "Bank Staff", "Staff within the bank.");

            bankStaff.Uses(mainframeBankingSystem, "Uses");

            // containers
            Container webApplication = internetBankingSystem.AddContainer("Web Application", "Provides all of the Internet banking functionality to customers.", "Java and Spring MVC");
            Container database       = internetBankingSystem.AddContainer("Database", "Stores interesting data.", "Relational Database Schema");

            database.AddTags(DatabaseTag);

            customer.Uses(webApplication, "Uses", "HTTPS");
            webApplication.Uses(database, "Reads from and writes to", "JDBC");
            webApplication.Uses(mainframeBankingSystem, "Uses", "XML/HTTPS");

            // components
            // - for a real-world software system, you would probably want to extract the components using
            // - static analysis/reflection rather than manually specifying them all
            Component homePageController           = webApplication.AddComponent("Home Page Controller", "Serves up the home page.", "Spring MVC Controller");
            Component signinController             = webApplication.AddComponent("Sign In Controller", "Allows users to sign in to the Internet Banking System.", "Spring MVC Controller");
            Component accountsSummaryController    = webApplication.AddComponent("Accounts Summary Controller", "Provides customers with an summary of their bank accounts.", "Spring MVC Controller");
            Component securityComponent            = webApplication.AddComponent("Security Component", "Provides functionality related to signing in, changing passwords, etc.", "Spring Bean");
            Component mainframeBankingSystemFacade = webApplication.AddComponent("Mainframe Banking System Facade", "A facade onto the mainframe banking system.", "Spring Bean");

            webApplication.Components.Where(c => "Spring MVC Controller".Equals(c.Technology)).ToList().ForEach(c => customer.Uses(c, "Uses", "HTTPS"));
            signinController.Uses(securityComponent, "Uses");
            accountsSummaryController.Uses(mainframeBankingSystemFacade, "Uses");
            securityComponent.Uses(database, "Reads from and writes to", "JDBC");
            mainframeBankingSystemFacade.Uses(mainframeBankingSystem, "Uses", "XML/HTTPS");

            // deployment nodes and container instances
            DeploymentNode developerLaptop = model.AddDeploymentNode("Developer Laptop", "A developer laptop.", "Windows 7 or 10");

            developerLaptop.AddDeploymentNode("Docker Container - Web Server", "A Docker container.", "Docker")
            .AddDeploymentNode("Apache Tomcat", "An open source Java EE web server.", "Apache Tomcat 8.x", 1, DictionaryUtils.Create("Xmx=512M", "Xms=1024M", "Java Version=8"))
            .Add(webApplication);

            developerLaptop.AddDeploymentNode("Docker Container - Database Server", "A Docker container.", "Docker")
            .AddDeploymentNode("Database Server", "A development database.", "Oracle 12c")
            .Add(database);

            DeploymentNode liveWebServer = model.AddDeploymentNode("bigbank-web***", "A web server residing in the web server farm, accessed via F5 BIG-IP LTMs.", "Ubuntu 16.04 LTS", 8, DictionaryUtils.Create("Location=London"));

            liveWebServer.AddDeploymentNode("Apache Tomcat", "An open source Java EE web server.", "Apache Tomcat 8.x", 1, DictionaryUtils.Create("Xmx=512M", "Xms=1024M", "Java Version=8"))
            .Add(webApplication);

            DeploymentNode primaryDatabaseServer = model.AddDeploymentNode("bigbank-db01", "The primary database server.", "Ubuntu 16.04 LTS", 1, DictionaryUtils.Create("Location=London"))
                                                   .AddDeploymentNode("Oracle - Primary", "The primary, live database server.", "Oracle 12c");

            primaryDatabaseServer.Add(database);

            DeploymentNode secondaryDatabaseServer = model.AddDeploymentNode("bigbank-db02", "The secondary database server.", "Ubuntu 16.04 LTS", 1, DictionaryUtils.Create("Location=Reading"))
                                                     .AddDeploymentNode("Oracle - Secondary", "A secondary, standby database server, used for failover purposes only.", "Oracle 12c");
            ContainerInstance secondaryDatabase = secondaryDatabaseServer.Add(database);

            model.Relationships.Where(r => r.Destination.Equals(secondaryDatabase)).ToList().ForEach(r => r.AddTags("Failover"));
            Relationship dataReplicationRelationship = primaryDatabaseServer.Uses(secondaryDatabaseServer, "Replicates data to", "");

            secondaryDatabase.AddTags("Failover");

            // views/diagrams
            EnterpriseContextView enterpriseContextView = views.CreateEnterpriseContextView("SystemLandscape", "The system landscape diagram for Big Bank plc.");

            enterpriseContextView.AddAllElements();
            enterpriseContextView.PaperSize = PaperSize.A5_Landscape;

            SystemContextView systemContextView = views.CreateSystemContextView(internetBankingSystem, "SystemContext", "The system context diagram for the Internet Banking System.");

            systemContextView.AddNearestNeighbours(internetBankingSystem);
            systemContextView.PaperSize = PaperSize.A5_Landscape;

            ContainerView containerView = views.CreateContainerView(internetBankingSystem, "Containers", "The container diagram for the Internet Banking System.");

            containerView.Add(customer);
            containerView.AddAllContainers();
            containerView.Add(mainframeBankingSystem);
            containerView.PaperSize = PaperSize.A5_Landscape;

            ComponentView componentView = views.CreateComponentView(webApplication, "Components", "The component diagram for the Web Application");

            componentView.AddAllContainers();
            componentView.AddAllComponents();
            componentView.Add(customer);
            componentView.Add(mainframeBankingSystem);
            componentView.PaperSize = PaperSize.A5_Landscape;

            if (usePaidFeatures)
            {
                // dynamic diagrams, deployment diagrams and corporate branding are not available with the Free Plan
                DynamicView dynamicView = views.CreateDynamicView(webApplication, "SignIn", "Summarises how the sign in feature works.");
                dynamicView.Add(customer, "Requests /signin from", signinController);
                dynamicView.Add(customer, "Submits credentials to", signinController);
                dynamicView.Add(signinController, "Calls isAuthenticated() on", securityComponent);
                dynamicView.Add(securityComponent, "select * from users u where username = ?", database);
                dynamicView.PaperSize = PaperSize.A5_Landscape;

                DeploymentView developmentDeploymentView = views.CreateDeploymentView(internetBankingSystem, "DevelopmentDeployment", "An example development deployment scenario for the Internet Banking System.");
                developmentDeploymentView.Add(developerLaptop);
                developmentDeploymentView.PaperSize = PaperSize.A5_Landscape;

                DeploymentView liveDeploymentView = views.CreateDeploymentView(internetBankingSystem, "LiveDeployment", "An example live deployment scenario for the Internet Banking System.");
                liveDeploymentView.Add(liveWebServer);
                liveDeploymentView.Add(primaryDatabaseServer);
                liveDeploymentView.Add(secondaryDatabaseServer);
                liveDeploymentView.Add(dataReplicationRelationship);
                liveDeploymentView.PaperSize = PaperSize.A5_Landscape;
            }

            // colours, shapes and other diagram styling
            Styles styles = views.Configuration.Styles;

            styles.Add(new ElementStyle(Tags.Element)
            {
                Color = "#ffffff"
            });
            styles.Add(new ElementStyle(Tags.SoftwareSystem)
            {
                Background = "#1168bd"
            });
            styles.Add(new ElementStyle(Tags.Container)
            {
                Background = "#438dd5"
            });
            styles.Add(new ElementStyle(Tags.Component)
            {
                Background = "#85bbf0", Color = "#000000"
            });
            styles.Add(new ElementStyle(Tags.Person)
            {
                Background = "#08427b", Shape = Shape.Person
            });
            styles.Add(new ElementStyle(DatabaseTag)
            {
                Shape = Shape.Cylinder
            });
            styles.Add(new ElementStyle("Failover")
            {
                Opacity = 25
            });
            styles.Add(new RelationshipStyle("Failover")
            {
                Opacity = 25, Position = 70
            });

            // documentation
            // - usually the documentation would be included from separate Markdown/AsciiDoc files, but this is just an example
            StructurizrDocumentationTemplate template = new StructurizrDocumentationTemplate(workspace);

            template.AddContextSection(internetBankingSystem, Format.Markdown,
                                       "Here is some context about the Internet Banking System...\n" +
                                       "![](embed:EnterpriseContext)\n" +
                                       "![](embed:SystemContext)\n" +
                                       "### Internet Banking System\n...\n" +
                                       "### Mainframe Banking System\n...\n");
            template.AddContainersSection(internetBankingSystem, Format.Markdown,
                                          "Here is some information about the containers within the Internet Banking System...\n" +
                                          "![](embed:Containers)\n" +
                                          "### Web Application\n...\n" +
                                          "### Database\n...\n");
            template.AddComponentsSection(webApplication, Format.Markdown,
                                          "Here is some information about the Web Application...\n" +
                                          "![](embed:Components)\n" +
                                          "### Sign in process\n" +
                                          "Here is some information about the Sign In Controller, including how the sign in process works...\n" +
                                          "![](embed:SignIn)");
            template.AddDevelopmentEnvironmentSection(internetBankingSystem, Format.AsciiDoc,
                                                      "Here is some information about how to set up a development environment for the Internet Banking System...\n" +
                                                      "image::embed:DevelopmentDeployment[]");
            template.AddDeploymentSection(internetBankingSystem, Format.AsciiDoc,
                                          "Here is some information about the live deployment environment for the Internet Banking System...\n" +
                                          "image::embed:LiveDeployment[]");

            return(workspace);
        }
 public void Test_Name_WithNoSoftwareSystemAndNoEnvironment()
 {
     deploymentView = Views.CreateDeploymentView("deployment", "Description");
     Assert.Equal("Deployment - Default", deploymentView.Name);
 }
 public void Test_Name_WithNoSoftwareSystemAndAnEnvironment()
 {
     deploymentView             = Views.CreateDeploymentView("deployment", "Description");
     deploymentView.Environment = "Live";
     Assert.Equal("Deployment - Live", deploymentView.Name);
 }
        static void Main()
        {
            Workspace workspace = new Workspace("Amazon Web Services Example", "An example AWS deployment architecture.");
            Model     model     = workspace.Model;

            SoftwareSystem softwareSystem = model.AddSoftwareSystem("Spring PetClinic", "Allows employees to view and manage information regarding the veterinarians, the clients, and their pets.");
            Container      webApplication = softwareSystem.AddContainer("Web Application", "Allows employees to view and manage information regarding the veterinarians, the clients, and their pets.", "Java and Spring Boot");

            webApplication.AddTags(SpringBootTag);
            Container database = softwareSystem.AddContainer("Database", "Stores information regarding the veterinarians, the clients, and their pets.", "Relational database schema");

            database.AddTags(DatabaseTag);

            webApplication.Uses(database, "Reads from and writes to", "JDBC/SSL");

            DeploymentNode amazonWebServices = model.AddDeploymentNode("Amazon Web Services");

            amazonWebServices.AddTags("Amazon Web Services - Cloud");
            DeploymentNode amazonRegion = amazonWebServices.AddDeploymentNode("US-East-1");

            amazonRegion.AddTags("Amazon Web Services - Region");
            DeploymentNode autoscalingGroup = amazonRegion.AddDeploymentNode("Autoscaling group");

            autoscalingGroup.AddTags("Amazon Web Services - Auto Scaling");
            DeploymentNode ec2 = autoscalingGroup.AddDeploymentNode("Amazon EC2");

            ec2.AddTags("Amazon Web Services - EC2");
            ContainerInstance webApplicationInstance = ec2.Add(webApplication);

            InfrastructureNode route53 = amazonRegion.AddInfrastructureNode("Route 53");

            route53.AddTags("Amazon Web Services - Route 53");

            InfrastructureNode elb = amazonRegion.AddInfrastructureNode("Elastic Load Balancer");

            elb.AddTags("Amazon Web Services - Elastic Load Balancing");

            route53.Uses(elb, "Forwards requests to", "HTTPS");
            elb.Uses(webApplicationInstance, "Forwards requests to", "HTTPS");

            DeploymentNode rds = amazonRegion.AddDeploymentNode("Amazon RDS");

            rds.AddTags("Amazon Web Services - RDS");
            DeploymentNode mySql = rds.AddDeploymentNode("MySQL");

            mySql.AddTags("Amazon Web Services - RDS_MySQL_instance");
            ContainerInstance databaseInstance = mySql.Add(database);

            ViewSet        views          = workspace.Views;
            DeploymentView deploymentView = views.CreateDeploymentView(softwareSystem, "AmazonWebServicesDeployment", "An example deployment diagram.");

            deploymentView.AddAllDeploymentNodes();

            deploymentView.AddAnimation(route53);
            deploymentView.AddAnimation(elb);
            deploymentView.AddAnimation(webApplicationInstance);
            deploymentView.AddAnimation(databaseInstance);

            Styles styles = views.Configuration.Styles;

            styles.Add(new ElementStyle(SpringBootTag)
            {
                Shape = Shape.RoundedBox, Background = "#ffffff"
            });
            styles.Add(new ElementStyle(DatabaseTag)
            {
                Shape = Shape.Cylinder, Background = "#ffffff"
            });
            styles.Add(new ElementStyle(Tags.InfrastructureNode)
            {
                Shape = Shape.RoundedBox, Background = "#ffffff"
            });

            views.Configuration.Theme = "https://raw.githubusercontent.com/structurizr/themes/master/amazon-web-services/theme.json";

            StructurizrClient structurizrClient = new StructurizrClient(ApiKey, ApiSecret);

            structurizrClient.PutWorkspace(WorkspaceId, workspace);
        }