Example #1
0
        public async Task CreateDeploymentTest(
            string deploymentName,
            string deviceGroupId,
            string deviceGroupQuery,
            string packageContent,
            int priority,
            string expectedException)
        {
            // Arrange
            var depModel = new DeploymentServiceModel()
            {
                Name             = deploymentName,
                DeviceGroupId    = deviceGroupId,
                DeviceGroupQuery = deviceGroupQuery,
                PackageContent   = packageContent,
                PackageType      = PackageType.EdgeManifest,
                Priority         = priority,
            };

            var newConfig = new Configuration("test-config")
            {
                Labels = new Dictionary <string, string>()
                {
                    { DeploymentNameLabel, deploymentName },
                    { this.packageTypeLabel, PackageType.EdgeManifest.ToString() },
                    { DeploymentGroupIdLabel, deviceGroupId },
                    { RmCreatedLabel, bool.TrueString },
                },
                Priority = priority,
            };

            this.registry.Setup(r => r.AddConfigurationAsync(It.Is <Configuration>(c =>
                                                                                   c.Labels.ContainsKey(DeploymentNameLabel) &&
                                                                                   c.Labels.ContainsKey(DeploymentGroupIdLabel) &&
                                                                                   c.Labels.ContainsKey(RmCreatedLabel) &&
                                                                                   c.Labels[DeploymentNameLabel] == deploymentName &&
                                                                                   c.Labels[DeploymentGroupIdLabel] == deviceGroupId &&
                                                                                   c.Labels[RmCreatedLabel] == bool.TrueString)))
            .ReturnsAsync(newConfig);

            this.tenantHelper.Setup(e => e.GetRegistry()).Returns(this.registry.Object);

            // Act
            if (string.IsNullOrEmpty(expectedException))
            {
                var createdDeployment = await this.deployments.CreateAsync(depModel);

                // Assert
                Assert.False(string.IsNullOrEmpty(createdDeployment.Id));
                Assert.Equal(deploymentName, createdDeployment.Name);
                Assert.Equal(deviceGroupId, createdDeployment.DeviceGroupId);
                Assert.Equal(priority, createdDeployment.Priority);
            }
            else
            {
                await Assert.ThrowsAsync(
                    Type.GetType(expectedException),
                    async() => await this.deployments.CreateAsync(depModel));
            }
        }
Example #2
0
        /// <summary>
        /// Schedules a deployment of the provided package, to the given group.
        /// </summary>
        /// <returns>Scheduled deployment</returns>
        public async Task <DeploymentServiceModel> CreateAsync(DeploymentServiceModel model)
        {
            if (string.IsNullOrEmpty(model.DeviceGroupId))
            {
                throw new ArgumentNullException(DEVICE_GROUP_ID_PARAM);
            }

            if (string.IsNullOrEmpty(model.DeviceGroupQuery))
            {
                throw new ArgumentNullException(DEVICE_GROUP_QUERY_PARAM);
            }

            if (string.IsNullOrEmpty(model.Name))
            {
                throw new ArgumentNullException(NAME_PARAM);
            }

            if (string.IsNullOrEmpty(model.PackageContent))
            {
                throw new ArgumentNullException(PACKAGE_CONTENT_PARAM);
            }

            if (model.Priority < 0)
            {
                throw new ArgumentOutOfRangeException(PRIORITY_PARAM,
                                                      model.Priority,
                                                      "The priority provided should be 0 or greater");
            }

            var edgeConfiguration = this.CreateEdgeConfiguration(model);

            // TODO: Add specific exception handling when exception types are exposed
            // https://github.com/Azure/azure-iot-sdk-csharp/issues/649
            return(new DeploymentServiceModel(await this.registry.AddConfigurationAsync(edgeConfiguration)));
        }
 public DeploymentApiModel(DeploymentServiceModel serviceModel)
 {
     this.CreatedDateTimeUtc = serviceModel.CreatedDateTimeUtc;
     this.DeploymentId       = serviceModel.Id;
     this.DeviceGroupId      = serviceModel.DeviceGroupId;
     this.DeviceGroupName    = serviceModel.DeviceGroupName;
     this.DeviceGroupQuery   = serviceModel.DeviceGroupQuery;
     this.Name           = serviceModel.Name;
     this.PackageContent = serviceModel.PackageContent;
     this.PackageName    = serviceModel.PackageName;
     this.PackageId      = serviceModel.PackageId;
     this.Priority       = serviceModel.Priority;
     this.PackageType    = serviceModel.PackageType;
     this.ConfigType     = serviceModel.ConfigType;
     this.IsActive       = !(serviceModel.Tags != null && serviceModel.Tags.Contains(InActiveTag));
     this.IsLatest       = serviceModel.Tags != null && serviceModel.Tags.Contains(LatestTag);
     this.Metrics        = new DeploymentMetricsApiModel(serviceModel.DeploymentMetrics)
     {
         DeviceStatuses = serviceModel.DeploymentMetrics?.DeviceStatuses,
     };
     this.Metadata = new Dictionary <string, string>
     {
         { "$type", $"DevicePropertyList;1" },
         { "$url", $"/v1/deviceproperties" },
     };
     this.CreatedDate  = serviceModel.CreatedDate;
     this.CreatedBy    = serviceModel.CreatedBy;
     this.ModifiedDate = serviceModel.ModifiedDate;
     this.ModifiedBy   = serviceModel.ModifiedBy;
 }
        public static Configuration ToHubConfiguration(DeploymentServiceModel model)
        {
            var packageConfiguration = JsonConvert.DeserializeObject <Configuration>(model.PackageContent);

            if (model.PackageType.Equals(PackageType.EdgeManifest) &&
                packageConfiguration.Content?.DeviceContent != null)
            {
                throw new InvalidInputException("Deployment type does not match with package contents.");
            }
            else if (model.PackageType.Equals(PackageType.DeviceConfiguration) &&
                     packageConfiguration.Content?.ModulesContent != null)
            {
                throw new InvalidInputException("Deployment type does not match with package contents.");
            }

            var deploymentId  = Guid.NewGuid().ToString().ToLower();
            var configuration = new Configuration(deploymentId);

            configuration.Content = packageConfiguration.Content;

            var targetCondition = QueryConditionTranslator.ToQueryString(model.DeviceGroupQuery);

            configuration.TargetCondition = string.IsNullOrEmpty(targetCondition) ? "*" : targetCondition;
            configuration.Priority        = model.Priority;
            configuration.ETag            = string.Empty;
            configuration.Labels          = packageConfiguration.Labels ?? new Dictionary <string, string>();

            // Required labels
            configuration.Labels[PACKAGE_TYPE_LABEL]        = model.PackageType.ToString();
            configuration.Labels[DEPLOYMENT_NAME_LABEL]     = model.Name;
            configuration.Labels[DEPLOYMENT_GROUP_ID_LABEL] = model.DeviceGroupId;
            configuration.Labels[RM_CREATED_LABEL]          = bool.TrueString;
            if (!String.IsNullOrEmpty(model.ConfigType))
            {
                configuration.Labels[CONFIG_TYPE_LABEL] = model.ConfigType;
            }

            var customMetrics = packageConfiguration.Metrics?.Queries;

            if (customMetrics != null)
            {
                configuration.Metrics.Queries = SubstituteDeploymentIdIfPresent(
                    customMetrics,
                    deploymentId);
            }

            // Add optional labels
            if (model.DeviceGroupName != null)
            {
                configuration.Labels[DEPLOYMENT_GROUP_NAME_LABEL] = model.DeviceGroupName;
            }

            if (model.PackageName != null)
            {
                configuration.Labels[DEPLOYMENT_PACKAGE_NAME_LABEL] = model.PackageName;
            }

            return(configuration);
        }
        public async Task VerifyGroupAndPackageNameLabelsTest()
        {
            // Arrange
            var deviceGroupId    = "dvcGroupId";
            var deviceGroupName  = "dvcGroupName";
            var deviceGroupQuery = "dvcGroupQuery";
            var packageName      = "packageName";
            var deploymentName   = "depName";
            var priority         = 10;
            var userid           = "testUser";
            var tenantId         = "testTenant";

            var depModel = new DeploymentServiceModel()
            {
                Name             = deploymentName,
                DeviceGroupId    = deviceGroupId,
                DeviceGroupName  = deviceGroupName,
                DeviceGroupQuery = deviceGroupQuery,
                PackageContent   = TestEdgePackageJson,
                PackageName      = packageName,
                Priority         = priority,
            };

            var newConfig = new Configuration("test-config")
            {
                Labels = new Dictionary <string, string>()
                {
                    { this.packageTypeLabel, PackageType.EdgeManifest.ToString() },
                    { DeploymentNameLabel, deploymentName },
                    { DeploymentGroupIdLabel, deviceGroupId },
                    { RmCreatedLabel, bool.TrueString },
                    { DeploymentGroupNameLabel, deviceGroupName },
                    { DeploymentPackageNameLabel, packageName },
                },
                Priority = priority,
            };

            this.registry.Setup(r => r.AddConfigurationAsync(It.Is <Configuration>(c =>
                                                                                   c.Labels.ContainsKey(DeploymentNameLabel) &&
                                                                                   c.Labels.ContainsKey(DeploymentGroupIdLabel) &&
                                                                                   c.Labels.ContainsKey(RmCreatedLabel) &&
                                                                                   c.Labels[DeploymentNameLabel] == deploymentName &&
                                                                                   c.Labels[DeploymentGroupIdLabel] == deviceGroupId &&
                                                                                   c.Labels[RmCreatedLabel] == bool.TrueString)))
            .ReturnsAsync(newConfig);

            this.tenantHelper.Setup(e => e.GetRegistry()).Returns(this.registry.Object);

            // Act
            var createdDeployment = await this.deployments.CreateAsync(depModel, userid, tenantId);

            // Assert
            Assert.False(string.IsNullOrEmpty(createdDeployment.Id));
            Assert.Equal(deploymentName, createdDeployment.Name);
            Assert.Equal(deviceGroupId, createdDeployment.DeviceGroupId);
            Assert.Equal(priority, createdDeployment.Priority);
            Assert.Equal(deviceGroupName, createdDeployment.DeviceGroupName);
            Assert.Equal(packageName, createdDeployment.PackageName);
        }
Example #6
0
        public async Task <DeploymentServiceModel> GetAsync(string deploymentId, bool includeDeviceStatus = false, bool isLatest = true)
        {
            if (string.IsNullOrEmpty(deploymentId))
            {
                throw new ArgumentNullException(nameof(deploymentId));
            }

            DeploymentServiceModel deployment = await this.GetDeploymentFromStorageAsync(deploymentId, true);

            isLatest = deployment.Tags.Contains(LatestTag);
            if (isLatest)
            {
                var deploymentFromHub = await this.tenantHelper.GetRegistry().GetConfigurationAsync(deploymentId);

                if (deploymentFromHub == null)
                {
                    throw new ResourceNotFoundException($"Deployment with id {deploymentId} not found.");
                }

                if (!this.CheckIfDeploymentWasMadeByRM(deploymentFromHub))
                {
                    throw new ResourceNotSupportedException($"Deployment with id {deploymentId}" + @" was
                                                        created externally and therefore not supported");
                }

                IDictionary <string, DeploymentStatus> deviceStatuses = this.GetDeviceStatuses(deploymentFromHub);

                return(new DeploymentServiceModel(deploymentFromHub)
                {
                    DeploymentMetrics =
                    {
                        DeviceMetrics  = this.CalculateDeviceMetrics(deviceStatuses),
                        DeviceStatuses = includeDeviceStatus ? deviceStatuses : null,
                    },
                    Tags = new List <string>()
                    {
                        LatestTag
                    },
                });
            }
            else
            {
                if (deployment != null && deployment.DeploymentMetrics != null)
                {
                    deployment.PackageContent = null;
                    if (deployment.DeploymentMetrics.DeviceStatuses == null)
                    {
                        deployment.DeploymentMetrics.DeviceStatuses = new Dictionary <string, DeploymentStatus>();
                    }

                    deployment.DeploymentMetrics.DeviceMetrics  = this.CalculateDeviceMetrics(deployment.DeploymentMetrics.DeviceStatuses);
                    deployment.DeploymentMetrics.DeviceStatuses = includeDeviceStatus ? deployment.DeploymentMetrics.DeviceStatuses : null;
                }

                return(deployment);
            }
        }
        private async Task <bool> UpdateMetricsOfCurrentDeployment(string deviceGroupId, int priority)
        {
            var deploymentsFromHub = await this.ListAsync();

            var deploymentsOfDeviceGroup = deploymentsFromHub.Items.Where(i => i.DeviceGroupId == deviceGroupId).OrderByDescending(p => p.Priority).ThenByDescending(q => q.CreatedDateTimeUtc);

            if (deploymentsOfDeviceGroup != null && deploymentsOfDeviceGroup.Count() > 0)
            {
                var deployment = deploymentsOfDeviceGroup.First();

                if (priority >= deployment.Priority)
                {
                    var deploymentDetails = await this.GetDeploymentAsync(deployment.Id);

                    DeploymentServiceModel currentDeployment = await this.GetDeploymentFromStorageAsync(deployment.Id);

                    // Update the Device Statuses for the DeploymentId for future references.
                    currentDeployment.DeploymentMetrics = new DeploymentMetricsServiceModel(deploymentDetails.SystemMetrics, deploymentDetails.Metrics);

                    currentDeployment.DeploymentMetrics.DeviceStatuses = this.GetDeviceStatuses(deploymentDetails);

                    var deviceTwins = await this.GetDeviceProperties(currentDeployment.DeploymentMetrics.DeviceStatuses.Keys);

                    // Since the deployment that will be created have highest priority, remove latest tag on current deployment
                    if (currentDeployment?.Tags != null)
                    {
                        var existingTag = currentDeployment.Tags.FirstOrDefault(t => t.Equals(LatestTag, StringComparison.OrdinalIgnoreCase));
                        if (existingTag != null)
                        {
                            currentDeployment.Tags.Remove(existingTag);
                        }
                    }

                    var value = JsonConvert.SerializeObject(
                        currentDeployment,
                        Formatting.Indented,
                        new JsonSerializerSettings
                    {
                        NullValueHandling = NullValueHandling.Ignore,
                    });

                    await this.client.UpdateAsync(DeploymentsCollection, currentDeployment.Id, value, currentDeployment.ETag);

                    await this.StoreDevicePropertiesInStorage(deviceTwins, currentDeployment.Id);

                    // Since the deployment that will be created have highest priority, mark it as the latest
                    return(true);
                }
                else
                {
                    return(false);
                }
            }

            return(true);
        }
Example #8
0
        public async Task VerifyGroupAndPackageNameLabelsTest()
        {
            // Arrange
            var deviceGroupId    = "dvcGroupId";
            var deviceGroupName  = "dvcGroupName";
            var deviceGroupQuery = "dvcGroupQuery";
            var packageName      = "packageName";
            var deploymentName   = "depName";
            var priority         = 10;
            var depModel         = new DeploymentServiceModel()
            {
                Name             = deploymentName,
                DeviceGroupId    = deviceGroupId,
                DeviceGroupName  = deviceGroupName,
                DeviceGroupQuery = deviceGroupQuery,
                PackageContent   = TEST_EDGE_PACKAGE_JSON,
                PackageName      = packageName,
                Priority         = priority
            };

            var newConfig = new Configuration("test-config")
            {
                Labels = new Dictionary <string, string>()
                {
                    { PACKAGE_TYPE_LABEL, PackageType.EdgeManifest.ToString() },
                    { DEPLOYMENT_NAME_LABEL, deploymentName },
                    { DEPLOYMENT_GROUP_ID_LABEL, deviceGroupId },
                    { RM_CREATED_LABEL, bool.TrueString },
                    { DEPLOYMENT_GROUP_NAME_LABEL, deviceGroupName },
                    { DEPLOYMENT_PACKAGE_NAME_LABEL, packageName }
                },
                Priority = priority
            };

            this.registry.Setup(r => r.AddConfigurationAsync(It.Is <Configuration>(c =>
                                                                                   c.Labels.ContainsKey(DEPLOYMENT_NAME_LABEL) &&
                                                                                   c.Labels.ContainsKey(DEPLOYMENT_GROUP_ID_LABEL) &&
                                                                                   c.Labels.ContainsKey(RM_CREATED_LABEL) &&
                                                                                   c.Labels[DEPLOYMENT_NAME_LABEL] == deploymentName &&
                                                                                   c.Labels[DEPLOYMENT_GROUP_ID_LABEL] == deviceGroupId &&
                                                                                   c.Labels[RM_CREATED_LABEL] == bool.TrueString)))
            .ReturnsAsync(newConfig);

            // Act
            var createdDeployment = await this.deployments.CreateAsync(depModel);

            // Assert
            Assert.False(string.IsNullOrEmpty(createdDeployment.Id));
            Assert.Equal(deploymentName, createdDeployment.Name);
            Assert.Equal(deviceGroupId, createdDeployment.DeviceGroupId);
            Assert.Equal(priority, createdDeployment.Priority);
            Assert.Equal(deviceGroupName, createdDeployment.DeviceGroupName);
            Assert.Equal(packageName, createdDeployment.PackageName);
        }
Example #9
0
        public async Task CreateDeploymentTest(string deploymentName, string deviceGroupId,
                                               string deviceGroupQuery, string packageContent,
                                               int priority, string expectedException)
        {
            // Arrange
            var depModel = new DeploymentServiceModel()
            {
                Name             = deploymentName,
                DeviceGroupId    = deviceGroupId,
                DeviceGroupQuery = deviceGroupQuery,
                PackageContent   = packageContent,
                PackageType      = PackageType.EdgeManifest,
                Priority         = priority
            };

            var newConfig = new Configuration("test-config")
            {
                Labels = new Dictionary <string, string>()
                {
                    { DEPLOYMENT_NAME_LABEL, deploymentName },
                    { PACKAGE_TYPE_LABEL, PackageType.EdgeManifest.ToString() },
                    { DEPLOYMENT_GROUP_ID_LABEL, deviceGroupId },
                    { RM_CREATED_LABEL, bool.TrueString },
                }, Priority = priority
            };

            this.registry.Setup(r => r.AddConfigurationAsync(It.Is <Configuration>(c =>
                                                                                   c.Labels.ContainsKey(DEPLOYMENT_NAME_LABEL) &&
                                                                                   c.Labels.ContainsKey(DEPLOYMENT_GROUP_ID_LABEL) &&
                                                                                   c.Labels.ContainsKey(RM_CREATED_LABEL) &&
                                                                                   c.Labels[DEPLOYMENT_NAME_LABEL] == deploymentName &&
                                                                                   c.Labels[DEPLOYMENT_GROUP_ID_LABEL] == deviceGroupId &&
                                                                                   c.Labels[RM_CREATED_LABEL] == bool.TrueString)))
            .ReturnsAsync(newConfig);

            // Act
            if (string.IsNullOrEmpty(expectedException))
            {
                var createdDeployment = await this.deployments.CreateAsync(depModel);

                // Assert
                Assert.False(string.IsNullOrEmpty(createdDeployment.Id));
                Assert.Equal(deploymentName, createdDeployment.Name);
                Assert.Equal(deviceGroupId, createdDeployment.DeviceGroupId);
                Assert.Equal(priority, createdDeployment.Priority);
            }
            else
            {
                await Assert.ThrowsAsync(Type.GetType(expectedException),
                                         async() => await this.deployments.CreateAsync(depModel));
            }
        }
        public async Task <DeploymentServiceModel> CreateAsync(DeploymentServiceModel model, string userId, string tenantId)
        {
            if (string.IsNullOrEmpty(model.DeviceGroupId))
            {
                throw new ArgumentNullException(DeviceGroupIdParameter);
            }

            if (string.IsNullOrEmpty(model.DeviceGroupQuery) && (model.DeviceIds == null || (model.DeviceIds != null && model.DeviceIds.Count() == 0)))
            {
                throw new ArgumentNullException(DeviceGroupQueryParameter);
            }

            if (string.IsNullOrEmpty(model.Name))
            {
                throw new ArgumentNullException(NameParameter);
            }

            if (string.IsNullOrEmpty(model.PackageContent))
            {
                throw new ArgumentNullException(PackageContentParameter);
            }

            if (model.PackageType.Equals(PackageType.DeviceConfiguration) &&
                string.IsNullOrEmpty(model.ConfigType))
            {
                throw new ArgumentNullException(ConfigurationTypeParameter);
            }

            if (model.Priority < 0)
            {
                throw new ArgumentOutOfRangeException(
                          PriorityParameter,
                          model.Priority,
                          "The priority provided should be 0 or greater");
            }

            var configuration = ConfigurationsHelper.ToHubConfiguration(model);

            // TODO: Add specific exception handling when exception types are exposed
            // https://github.com/Azure/azure-iot-sdk-csharp/issues/649
            var result = new DeploymentServiceModel(await this.tenantHelper.GetRegistry().AddConfigurationAsync(configuration));

            // Setting the id so that deployment id is populated
            model.Id = result.Id;

            // Log a custom event to Application Insights
            this.deploymentLog.LogDeploymentCreate(model, tenantId, userId);

            return(result);
        }
Example #11
0
 public DeploymentApiModel(DeploymentServiceModel serviceModel,
                           IDictionary <string, DeploymentStatus> deviceStatuses)
 {
     this.CreatedDateTimeUtc = serviceModel.CreatedDateTimeUtc;
     this.DeploymentId       = serviceModel.Id;
     this.DeviceGroupId      = serviceModel.DeviceGroupId;
     this.Name     = serviceModel.Name;
     this.Priority = serviceModel.Priority;
     this.Type     = serviceModel.Type;
     this.Metrics  = new DeploymentMetricsApiModel(serviceModel.DeploymentMetrics)
     {
         DeviceStatuses = deviceStatuses
     };
 }
Example #12
0
 public DeploymentApiModel(DeploymentServiceModel serviceModel)
 {
     this.CreatedDateTimeUtc = serviceModel.CreatedDateTimeUtc;
     this.DeploymentId       = serviceModel.Id;
     this.DeviceGroupId      = serviceModel.DeviceGroupId;
     this.DeviceGroupName    = serviceModel.DeviceGroupName;
     this.DeviceGroupQuery   = serviceModel.DeviceGroupQuery;
     this.Name           = serviceModel.Name;
     this.PackageContent = serviceModel.PackageContent;
     this.PackageName    = serviceModel.PackageName;
     this.Priority       = serviceModel.Priority;
     this.Type           = serviceModel.Type;
     this.Metrics        = new DeploymentMetricsApiModel(serviceModel.DeploymentMetrics)
     {
         DeviceStatuses = serviceModel.DeploymentMetrics?.DeviceStatuses
     };
 }
        public async Task <DeploymentServiceModel> CreateAsync(DeploymentServiceModel model)
        {
            if (string.IsNullOrEmpty(model.DeviceGroupId))
            {
                throw new ArgumentNullException(DeviceGroupIdParameter);
            }

            if (string.IsNullOrEmpty(model.DeviceGroupQuery))
            {
                throw new ArgumentNullException(DeviceGroupQueryParameter);
            }

            if (string.IsNullOrEmpty(model.Name))
            {
                throw new ArgumentNullException(NameParameter);
            }

            if (string.IsNullOrEmpty(model.PackageContent))
            {
                throw new ArgumentNullException(PackageContentParameter);
            }

            if (model.PackageType.Equals(PackageType.DeviceConfiguration) &&
                string.IsNullOrEmpty(model.ConfigType))
            {
                throw new ArgumentNullException(ConfigurationTypeParameter);
            }

            if (model.Priority < 0)
            {
                throw new ArgumentOutOfRangeException(
                          PriorityParameter,
                          model.Priority,
                          "The priority provided should be 0 or greater");
            }

            var configuration = ConfigurationsHelper.ToHubConfiguration(model);

            // TODO: Add specific exception handling when exception types are exposed
            // https://github.com/Azure/azure-iot-sdk-csharp/issues/649
            return(new DeploymentServiceModel(await this.tenantHelper.GetRegistry().AddConfigurationAsync(configuration)));
        }
        private ValueApiModel CreateDeploymentStorageData(int idx, bool isLatest = true)
        {
            // Arrange
            var deviceGroupId    = "dvcGroupId";
            var deviceGroupName  = "dvcGroupName";
            var deviceGroupQuery = "dvcGroupQuery";
            var packageName      = "packageName";
            var deploymentName   = "deployment";
            var priority         = 10;
            var userid           = "testUser";

            var deployment = new DeploymentServiceModel()
            {
                Name               = deploymentName + idx,
                DeviceGroupId      = deviceGroupId,
                DeviceGroupName    = deviceGroupName,
                DeviceGroupQuery   = deviceGroupQuery,
                PackageContent     = TestEdgePackageJson,
                PackageName        = packageName,
                Priority           = priority,
                CreatedBy          = userid,
                CreatedDateTimeUtc = DateTime.UtcNow,
                CreatedDateTime    = DateTime.UtcNow,
                DeploymentMetrics  = new DeploymentMetricsServiceModel()
                {
                    DeviceStatuses = new Dictionary <string, DeploymentStatus> {
                        { "device1", DeploymentStatus.Pending }
                    }
                },
                Tags = isLatest ? new List <string>()
                {
                    "reserved.latest"
                } : new List <string>(),
            };
            var           jsonValue = JsonConvert.SerializeObject(deployment);
            ValueApiModel value     = new ValueApiModel()
            {
                Key = idx.ToString(), Data = jsonValue
            };

            return(value);
        }
        private async Task <DeploymentServiceModel> MarkDeploymentAsDeleted(DeploymentServiceModel existingDeployment, string userId)
        {
            if (existingDeployment != null)
            {
                existingDeployment.Tags.Add(DeleteTag);

                AuditHelper.UpdateAuditingData(existingDeployment, userId);

                var value = JsonConvert.SerializeObject(
                    existingDeployment,
                    Formatting.Indented,
                    new JsonSerializerSettings
                {
                    NullValueHandling = NullValueHandling.Ignore,
                });
                var response = await this.client.UpdateAsync(DeploymentsCollection, existingDeployment.Id, value, existingDeployment.ETag);
            }

            return(existingDeployment);
        }
        private async Task StoreDeploymentInSecondaryStorage(DeploymentServiceModel deployment, string userId)
        {
            if (string.IsNullOrWhiteSpace(deployment.ETag))
            {
                AuditHelper.AddAuditingData(deployment, userId);
            }
            else
            {
                AuditHelper.UpdateAuditingData(deployment, userId);
            }

            var value = JsonConvert.SerializeObject(
                deployment,
                Formatting.Indented,
                new JsonSerializerSettings
            {
                NullValueHandling = NullValueHandling.Ignore,
            });

            var response = await this.client.UpdateAsync(DeploymentsCollection, deployment.Id, value, deployment.ETag);
        }
        public void LogDeploymentCreate(DeploymentServiceModel deployment, string tenantId, string userId)
        {
            var eventInfo = new CustomEvent
            {
                EventSource      = Convert.ToString(EventSource.IotHubManager),
                EventType        = Convert.ToString(EventType.DeploymentCreate),
                EventTime        = DateTimeOffset.UtcNow.ToString(AppInsightDateFormat),
                EventDescription = $@"Deployment created by User {userId} for package {deployment.PackageName} targeting {deployment.DeviceGroupName} Devicegroup",
                TenantId         = tenantId,
                PackageId        = deployment.PackageId,
                PackageName      = deployment.PackageName,
                DeviceGroup      = deployment.DeviceGroupName,
                PackageType      = deployment.PackageType.ToString(),
                UserId           = userId,
                DeploymentId     = deployment.Id,
                DeploymentName   = deployment.Name,
            };

            this.LogCustomEvent($"{tenantId.Substring(0, 8)}-{deployment.Id}", deployment.Name, eventInfo);
            this.LogCustomEvent($"{tenantId.Substring(0, 8)}-{deployment.PackageId}", deployment.Name, eventInfo);
        }
Example #18
0
 public DeploymentApiModel(DeploymentServiceModel serviceModel)
 {
     this.CreatedDateTimeUtc = serviceModel.CreatedDateTimeUtc;
     this.DeploymentId       = serviceModel.Id;
     this.DeviceGroupId      = serviceModel.DeviceGroupId;
     this.DeviceGroupName    = serviceModel.DeviceGroupName;
     this.DeviceGroupQuery   = serviceModel.DeviceGroupQuery;
     this.Name           = serviceModel.Name;
     this.PackageContent = serviceModel.PackageContent;
     this.PackageName    = serviceModel.PackageName;
     this.Priority       = serviceModel.Priority;
     this.PackageType    = serviceModel.PackageType;
     this.ConfigType     = serviceModel.ConfigType;
     this.Metrics        = new DeploymentMetricsApiModel(serviceModel.DeploymentMetrics)
     {
         DeviceStatuses = serviceModel.DeploymentMetrics?.DeviceStatuses
     };
     this.Metadata = new Dictionary <string, string>
     {
         { "$type", $"DevicePropertyList;{Version.NUMBER}" },
         { "$url", $"/{Version.PATH}/deviceproperties" }
     };
 }
Example #19
0
        private Configuration CreateEdgeConfiguration(DeploymentServiceModel model)
        {
            var deploymentId             = Guid.NewGuid().ToString().ToLower();
            var edgeConfiguration        = new Configuration(deploymentId);
            var packageEdgeConfiguration = JsonConvert.DeserializeObject <Configuration>(model.PackageContent);

            edgeConfiguration.Content = packageEdgeConfiguration.Content;

            var targetCondition = QueryConditionTranslator.ToQueryString(model.DeviceGroupQuery);

            edgeConfiguration.TargetCondition = string.IsNullOrEmpty(targetCondition) ? "*" : targetCondition;
            edgeConfiguration.Priority        = model.Priority;
            edgeConfiguration.ETag            = string.Empty;

            if (edgeConfiguration.Labels == null)
            {
                edgeConfiguration.Labels = new Dictionary <string, string>();
            }

            // Required labels
            edgeConfiguration.Labels.Add(DEPLOYMENT_NAME_LABEL, model.Name);
            edgeConfiguration.Labels.Add(DEPLOYMENT_GROUP_ID_LABEL, model.DeviceGroupId);
            edgeConfiguration.Labels.Add(RM_CREATED_LABEL, bool.TrueString);

            // Add optional labels
            if (model.DeviceGroupName != null)
            {
                edgeConfiguration.Labels.Add(DEPLOYMENT_GROUP_NAME_LABEL, model.DeviceGroupName);
            }
            if (model.PackageName != null)
            {
                edgeConfiguration.Labels.Add(DEPLOYMENT_PACKAGE_NAME_LABEL, model.PackageName);
            }

            return(edgeConfiguration);
        }
        public async Task CreateDeploymentTest(
            string deploymentName,
            string deviceGroupId,
            string deviceGroupQuery,
            string packageContent,
            int priority,
            string expectedException)
        {
            // Arrange
            var depModel = new DeploymentServiceModel()
            {
                Name             = deploymentName,
                DeviceGroupId    = deviceGroupId,
                DeviceGroupQuery = deviceGroupQuery,
                PackageContent   = packageContent,
                PackageType      = PackageType.EdgeManifest,
                Priority         = priority,
            };

            var userId   = "testUser";
            var tenantId = "testTenat";

            var existingConfig = new Configuration("test-config1")
            {
                Labels = new Dictionary <string, string>()
                {
                    { DeploymentNameLabel, deploymentName },
                    { this.packageTypeLabel, PackageType.EdgeManifest.ToString() },
                    { DeploymentGroupIdLabel, deviceGroupId },
                    { RmCreatedLabel, bool.TrueString },
                },
                Priority = priority,
            };

            var newConfig = new Configuration("test-config")
            {
                Labels = new Dictionary <string, string>()
                {
                    { DeploymentNameLabel, deploymentName },
                    { this.packageTypeLabel, PackageType.EdgeManifest.ToString() },
                    { DeploymentGroupIdLabel, deviceGroupId },
                    { RmCreatedLabel, bool.TrueString },
                },
                Priority = priority,
            };

            this.registry.Setup(r => r.AddConfigurationAsync(It.Is <Configuration>(c =>
                                                                                   c.Labels.ContainsKey(DeploymentNameLabel) &&
                                                                                   c.Labels.ContainsKey(DeploymentGroupIdLabel) &&
                                                                                   c.Labels.ContainsKey(RmCreatedLabel) &&
                                                                                   c.Labels[DeploymentNameLabel] == deploymentName &&
                                                                                   c.Labels[DeploymentGroupIdLabel] == deviceGroupId &&
                                                                                   c.Labels[RmCreatedLabel] == bool.TrueString)))
            .ReturnsAsync(newConfig);

            this.registry.Setup(r => r.CreateQuery(It.IsAny <string>())).Returns(new ResultQuery(0));

            this.registry.Setup(r => r.GetConfigurationAsync(It.IsAny <string>())).ReturnsAsync(existingConfig);

            this.tenantHelper.Setup(e => e.GetRegistry()).Returns(this.registry.Object);

            this.storageAdapterClient.Setup(s => s.UpdateAsync(
                                                It.IsAny <string>(),
                                                It.IsAny <string>(),
                                                It.IsAny <string>(),
                                                It.IsAny <string>())).ReturnsAsync(new ValueApiModel());

            this.storageAdapterClient.Setup(s => s.CreateAsync(
                                                It.IsAny <string>(),
                                                It.IsAny <string>())).ReturnsAsync(new ValueApiModel());

            var deploymentStorageData = this.CreateDeploymentStorageData(0);

            this.storageAdapterClient.Setup(r => r.GetAsync(It.IsAny <string>(), It.IsAny <string>())).ReturnsAsync(deploymentStorageData);

            this.devices.Setup(d => d.GetListAsync(It.IsAny <string>(), It.IsAny <string>())).ReturnsAsync(new DeviceServiceListModel(new List <DeviceServiceModel>()));

            var configurations = new List <Configuration>();

            configurations.Add(existingConfig);

            this.registry.Setup(r => r.GetConfigurationsAsync(1000)).ReturnsAsync(configurations);
            this.tenantHelper.Setup(e => e.GetRegistry()).Returns(this.registry.Object);

            // Act
            if (string.IsNullOrEmpty(expectedException))
            {
                var createdDeployment = await this.deployments.CreateAsync(depModel, userId, tenantId);

                // Assert
                Assert.False(string.IsNullOrEmpty(createdDeployment.Id));
                Assert.Equal(deploymentName, createdDeployment.Name);
                Assert.Equal(deviceGroupId, createdDeployment.DeviceGroupId);
                Assert.Equal(priority, createdDeployment.Priority);
            }
            else
            {
                await Assert.ThrowsAsync(
                    Type.GetType(expectedException),
                    async() => await this.deployments.CreateAsync(depModel, userId, tenantId));
            }
        }
Example #21
0
        public static Configuration ToHubConfiguration(DeploymentServiceModel model)
        {
            var packageConfiguration = JsonConvert.DeserializeObject <Configuration>(model.PackageContent);

            if (model.PackageType.Equals(PackageType.EdgeManifest) &&
                packageConfiguration.Content?.DeviceContent != null)
            {
                throw new InvalidInputException("Deployment type does not match with package contents.");
            }
            else if (model.PackageType.Equals(PackageType.DeviceConfiguration) &&
                     packageConfiguration.Content?.ModulesContent != null)
            {
                throw new InvalidInputException("Deployment type does not match with package contents.");
            }

            var deploymentId  = Guid.NewGuid().ToString().ToLower();
            var configuration = new Configuration(deploymentId);

            configuration.Content = packageConfiguration.Content;

            var targetCondition = QueryConditionTranslator.ToQueryString(model.DeviceGroupQuery);

            if (model.DeviceIds != null && model.DeviceIds.Any())
            {
                string deviceIdCondition = $"({string.Join(" or ", model.DeviceIds.Select(v => $"deviceId = '{v}'"))})";
                if (!string.IsNullOrWhiteSpace(targetCondition))
                {
                    string[] conditions = { targetCondition, deviceIdCondition };
                    targetCondition = string.Join(" or ", conditions);
                }
                else
                {
                    targetCondition = deviceIdCondition;
                }
            }

            configuration.TargetCondition = string.IsNullOrEmpty(targetCondition) ? "*" : targetCondition;
            configuration.Priority        = model.Priority;
            configuration.ETag            = string.Empty;
            configuration.Labels          = packageConfiguration.Labels ?? new Dictionary <string, string>();

            // Required labels
            configuration.Labels[PackageTypeLabel]       = model.PackageType.ToString();
            configuration.Labels[DeploymentNameLabel]    = model.Name;
            configuration.Labels[DeploymentGroupIdLabel] = model.DeviceGroupId;
            configuration.Labels[RmCreatedLabel]         = bool.TrueString;
            if (!string.IsNullOrEmpty(model.ConfigType))
            {
                configuration.Labels[ConfigTypeLabel] = model.ConfigType;
            }

            var customMetrics = packageConfiguration.Metrics?.Queries;

            if (customMetrics != null)
            {
                configuration.Metrics.Queries = SubstituteDeploymentIdIfPresent(
                    customMetrics,
                    deploymentId);
            }

            // Add optional labels
            if (model.DeviceGroupName != null)
            {
                configuration.Labels[DeploymentGroupNameLabel] = model.DeviceGroupName;
            }

            if (model.PackageName != null)
            {
                configuration.Labels[DeploymentPackageNameLabel] = model.PackageName;
            }

            return(configuration);
        }
        public async Task <DeploymentServiceModel> CreateAsync(DeploymentServiceModel model, string userId, string tenantId)
        {
            if (string.IsNullOrEmpty(model.DeviceGroupId))
            {
                throw new ArgumentNullException(DeviceGroupIdParameter);
            }

            if (string.IsNullOrEmpty(model.DeviceGroupQuery) && (model.DeviceIds == null || (model.DeviceIds != null && model.DeviceIds.Count() == 0)))
            {
                throw new ArgumentNullException(DeviceGroupQueryParameter);
            }

            if (string.IsNullOrEmpty(model.Name))
            {
                throw new ArgumentNullException(NameParameter);
            }

            if (string.IsNullOrEmpty(model.PackageContent))
            {
                throw new ArgumentNullException(PackageContentParameter);
            }

            if (model.PackageType.Equals(PackageType.DeviceConfiguration) &&
                string.IsNullOrEmpty(model.ConfigType))
            {
                throw new ArgumentNullException(ConfigurationTypeParameter);
            }

            if (model.Priority < 0)
            {
                throw new ArgumentOutOfRangeException(
                          PriorityParameter,
                          model.Priority,
                          "The priority provided should be 0 or greater");
            }

            var configuration = ConfigurationsHelper.ToHubConfiguration(model);

            // Update the Metrics related to previous deployment which targets the same device group as the metrics
            // will be overriden once the new deployment gets applied to the devices.
            bool shouldMarkAsLatest = await this.UpdateMetricsOfCurrentDeployment(model.DeviceGroupId, model.Priority);

            // TODO: Add specific exception handling when exception types are exposed
            // https://github.com/Azure/azure-iot-sdk-csharp/issues/649
            var result = new DeploymentServiceModel(await this.tenantHelper.GetRegistry().AddConfigurationAsync(configuration));

            // Setting the id so that deployment id is populated
            model.Id = result.Id;
            model.CreatedDateTimeUtc = result.CreatedDateTimeUtc;

            // Add latest tag to deployment if deployment has highest priority for the device group.
            if (shouldMarkAsLatest)
            {
                if (model.Tags == null)
                {
                    model.Tags = new List <string>();
                }

                model.Tags.Add(LatestTag);
            }
            else
            {
                // Update the Device Statuses for the DeploymentId for future references.
                model.DeploymentMetrics = result.DeploymentMetrics;
            }

            // Store the deployment details in Cosmos DB
            await this.StoreDeploymentInSecondaryStorage(model, userId);

            // Log a custom event to Application Insights
            // this.deploymentLog.LogDeploymentCreate(model, tenantId, userId);
            return(model);
        }
        private async Task <DeploymentServiceModel> MarkDeploymentAsInactive(DeploymentServiceModel existingDeployment, string userId, List <TwinServiceModel> deviceTwins, bool isDelete)
        {
            if (existingDeployment != null)
            {
                if (existingDeployment.Tags == null)
                {
                    existingDeployment.Tags = new List <string>();
                }

                if (existingDeployment.Tags.Contains(InActiveTag, StringComparer.InvariantCultureIgnoreCase))
                {
                    return(existingDeployment);
                }

                existingDeployment.Tags.Add(InActiveTag);
                if (isDelete)
                {
                    existingDeployment.Tags.Add(DeleteTag);
                }

                bool isLatestDeployment = existingDeployment.Tags.Contains(LatestTag, StringComparer.InvariantCultureIgnoreCase);

                if (isLatestDeployment)
                {
                    existingDeployment.Tags.Remove(LatestTag);
                }

                AuditHelper.UpdateAuditingData(existingDeployment, userId);

                var value = JsonConvert.SerializeObject(
                    existingDeployment,
                    Formatting.Indented,
                    new JsonSerializerSettings
                {
                    NullValueHandling = NullValueHandling.Ignore,
                });
                var response = await this.client.UpdateAsync(DeploymentsCollection, existingDeployment.Id, value, existingDeployment.ETag);

                if (deviceTwins != null && deviceTwins.Count > 0)
                {
                    await this.StoreDevicePropertiesInStorage(deviceTwins, existingDeployment.Id);
                }

                if (isLatestDeployment)
                {
                    // Mark the deployment with highest priority and which is created last as the latest deployment.
                    var deployments = await this.ListAsync();

                    if (deployments != null && deployments.Items.Count > 0)
                    {
                        var deploymentsOfDeviceGroup = deployments.Items.Where(i => i.DeviceGroupId == existingDeployment.DeviceGroupId).OrderByDescending(p => p.Priority).ThenByDescending(q => q.CreatedDateTimeUtc);

                        if (deploymentsOfDeviceGroup != null && deploymentsOfDeviceGroup.Count() > 0)
                        {
                            var latestDeployment = deploymentsOfDeviceGroup.First();

                            var latestDeploymentFromStorage = await this.GetDeploymentFromStorageAsync(latestDeployment.Id);

                            if (latestDeploymentFromStorage != null)
                            {
                                if (latestDeploymentFromStorage.Tags == null)
                                {
                                    latestDeploymentFromStorage.Tags = new List <string>();
                                }

                                if (!latestDeploymentFromStorage.Tags.Contains(LatestTag))
                                {
                                    latestDeploymentFromStorage.Tags.Add(LatestTag);

                                    var storageValue = JsonConvert.SerializeObject(
                                        latestDeploymentFromStorage,
                                        Formatting.Indented,
                                        new JsonSerializerSettings
                                    {
                                        NullValueHandling = NullValueHandling.Ignore,
                                    });
                                    await this.client.UpdateAsync(DeploymentsCollection, latestDeployment.Id, storageValue, latestDeploymentFromStorage.ETag);
                                }
                            }
                        }
                    }
                }
            }

            return(existingDeployment);
        }
Example #24
0
        private async Task <(bool ShouldMarkAsLatest, string DeploymentId)> UpdateMetricsOfCurrentDeployment(string deviceGroupId, int priority, string tenantId)
        {
            var deploymentsFromHub = await this.ListAsync();

            var deploymentsOfDeviceGroup = deploymentsFromHub.Items.Where(i => i.DeviceGroupId == deviceGroupId).OrderByDescending(p => p.Priority).ThenByDescending(q => q.CreatedDateTimeUtc);

            string deploymentId = string.Empty;

            if (deploymentsOfDeviceGroup != null && deploymentsOfDeviceGroup.Count() > 0)
            {
                var deployment = deploymentsOfDeviceGroup.First();

                if (priority >= deployment.Priority)
                {
                    var getDeploymentFromHub = this.GetDeploymentAsync(deployment.Id);

                    var getDeploymentFromCOSMOS = this.GetDeploymentFromStorageAsync(deployment.Id);

                    await Task.WhenAll(getDeploymentFromHub, getDeploymentFromCOSMOS);

                    var deploymentDetails = await getDeploymentFromHub;

                    DeploymentServiceModel currentDeployment = await getDeploymentFromCOSMOS;

                    // Update the Device Statuses for the DeploymentId for future references.
                    currentDeployment.DeploymentMetrics = new DeploymentMetricsServiceModel(deploymentDetails.SystemMetrics, deploymentDetails.Metrics);

                    // Save device statuses in a separate collection
                    this.SaveDeviceStatuses(this.GetDeviceStatuses(deploymentDetails), deployment.Id);

                    if (string.IsNullOrWhiteSpace(currentDeployment.TargetCondition))
                    {
                        currentDeployment.TargetCondition = deploymentDetails.TargetCondition;
                    }

                    // Since the deployment that will be created have highest priority, remove latest tag on current deployment
                    if (currentDeployment?.Tags != null)
                    {
                        var existingTag = currentDeployment.Tags.FirstOrDefault(t => t.Equals(LatestTag, StringComparison.OrdinalIgnoreCase));
                        if (existingTag != null)
                        {
                            currentDeployment.Tags.Remove(existingTag);
                        }
                    }

                    var value = JsonConvert.SerializeObject(
                        currentDeployment,
                        Formatting.Indented,
                        new JsonSerializerSettings
                    {
                        NullValueHandling = NullValueHandling.Ignore,
                    });

                    var updateDeployment = await this.client.UpdateAsync(DeploymentsCollection, currentDeployment.Id, value, currentDeployment.ETag);

                    return(true, currentDeployment.Id);
                }
                else
                {
                    return(false, deploymentId);
                }
            }

            // Since the deployment that will be created have highest priority, mark it as the latest
            return(true, deploymentId);
        }