public CloudBackend(Workspace workspace, IInfrastructureEnvironment environment)
        {
            System = workspace.Model.AddSoftwareSystem(
                Location.Internal,
                "Azure IoT system",
                "Azure cloud based backend for processing data created on sensors / devices");

            SecretStorage       = new SecretStorage(this, environment);
            CloudGateway        = new CloudGateway(this, environment);
            DeviceProvisioning  = new DeviceProvisioning(this, CloudGateway, environment);
            TelemetryStorage    = new TelemetryStorage(this, environment);
            ApplicationInsights = new ApplicationInsights(this, environment);
            MasterDataStorage   = new MasterDataStorage(this, new SqlServer(environment), environment);
            SanitizedMessages   = new SanitizedMessages(this, new EventHubNamespace(environment), environment);
            Ingress             = new Ingress(this, CloudGateway, TelemetryStorage, MasterDataStorage, SanitizedMessages, ApplicationInsights, environment);
            StreamAnalytics     = new StreamAnalytics(this, SanitizedMessages, TelemetryStorage, environment);
            RestApi             = new RestApi(this, TelemetryStorage, MasterDataStorage, ApplicationInsights, environment);
            UserInterface       = new UserInterface(this, RestApi, environment);

            Device = workspace.Model.AddSoftwareSystem(Location.External, "Device", "Sends data into the cloud");
            Device.Uses(CloudGateway, "Send telemetry data and failure events", "MQTT");
            Device.Uses(DeviceProvisioning, "Provision device", "HTTPS");

            User = workspace.Model.AddPerson("User", "Person using the system to view data and take action on it");
            User.Uses(UserInterface, "View devices and their raw and aggregated data");

            StoreSecretsInKeyVault();
        }
        public Ingress(CloudBackend cloudBackend, CloudGateway hub,
                       TelemetryStorage telemetryStorage,
                       MasterDataStorage masterDataStorage,
                       SanitizedMessages sanitizedMessages,
                       ApplicationInsights applicationInsights,
                       IInfrastructureEnvironment environment)
        {
            Container = cloudBackend.System.AddContainer(
                name: "Ingress",
                description: "Receives incoming data from the cloud gateway and saves it into master data and telemetry data storages",
                technology: "Azure Function");

            Infrastructure = new FunctionAppService
            {
                Name = "ref-ingress-" + environment.Name
            };

            Uses(hub)
            .Over <IoTHubSDK>()
            .InOrderTo("Subscribes to incoming messages");

            Uses(sanitizedMessages)
            .Over <EventHubSDK>()
            .InOrderTo("Publish sanitized messages");

            Uses(telemetryStorage)
            .Over(telemetryStorage.Infrastructure.TableEndpoint)
            .InOrderTo("Persist telemetry data");

            Uses(masterDataStorage).InOrderTo("Persist master data");

            Uses(applicationInsights).InOrderTo("Log metrics");
        }
        public RestApi(CloudBackend cloudBackend, TelemetryStorage telemetryStorage, MasterDataStorage masterDataStorage, ApplicationInsights applicationInsights, IInfrastructureEnvironment environment)
        {
            Container = cloudBackend.System.AddContainer(
                name: "REST Api",
                description: "Implements endpoint required by the UI to load data",
                technology: "Azure App Service");

            Infrastructure = new WebAppService
            {
                Name = "ref-api-" + environment.Name,
                EnvironmentInvariantName = "ref-api"
            };

            Uses(telemetryStorage).Over(telemetryStorage.Infrastructure.TableEndpoint).InOrderTo("Load telemetry data");
            Uses(masterDataStorage).InOrderTo("Load master data");
            Uses(applicationInsights).InOrderTo("Log metrics");
        }