From 487ec97dd101415b93c2f8458003674243800b71 Mon Sep 17 00:00:00 2001 From: ssgueye2 Date: Wed, 24 May 2023 17:21:30 +0200 Subject: [PATCH 1/5] retrieve json attribute from Recipe --- .../EdgeModels/CreateEdgeModelsPage.razor | 20 +-- .../ConfigHandler.cs | 1 + .../ConfigHandlerBase.cs | 1 + .../DevelopmentConfigHandler.cs | 1 + .../ProductionAWSConfigHandler.cs | 2 + .../ProductionAzureConfigHandler.cs | 2 + .../Services/AWS/AwsConfigService.cs | 117 +++++++++++++++++- .../Services/EdgeModelService.cs | 49 ++++---- 8 files changed, 156 insertions(+), 37 deletions(-) diff --git a/src/AzureIoTHub.Portal.Client/Pages/EdgeModels/CreateEdgeModelsPage.razor b/src/AzureIoTHub.Portal.Client/Pages/EdgeModels/CreateEdgeModelsPage.razor index e436c0c23..7226764f4 100644 --- a/src/AzureIoTHub.Portal.Client/Pages/EdgeModels/CreateEdgeModelsPage.razor +++ b/src/AzureIoTHub.Portal.Client/Pages/EdgeModels/CreateEdgeModelsPage.razor @@ -196,17 +196,17 @@ - - - - Labels - - - - - - } + + + + Labels + + + + + + diff --git a/src/AzureIoTHub.Portal.Domain/ConfigHandler.cs b/src/AzureIoTHub.Portal.Domain/ConfigHandler.cs index c38f5d5b3..97724719b 100644 --- a/src/AzureIoTHub.Portal.Domain/ConfigHandler.cs +++ b/src/AzureIoTHub.Portal.Domain/ConfigHandler.cs @@ -80,5 +80,6 @@ public abstract class ConfigHandler public abstract string AWSRegion { get; } public abstract string AWSS3StorageConnectionString { get; } public abstract string AWSBucketName { get; } + public abstract string AWSAccountId { get; } } } diff --git a/src/AzureIoTHub.Portal.Infrastructure/ConfigHandlerBase.cs b/src/AzureIoTHub.Portal.Infrastructure/ConfigHandlerBase.cs index f5b8f3454..a87743b92 100644 --- a/src/AzureIoTHub.Portal.Infrastructure/ConfigHandlerBase.cs +++ b/src/AzureIoTHub.Portal.Infrastructure/ConfigHandlerBase.cs @@ -57,6 +57,7 @@ internal abstract class ConfigHandlerBase : ConfigHandler internal const string AWSRegionKey = "AWS:Region"; internal const string AWSS3StorageConnectionStringKey = "AWS:S3Storage:ConnectionString"; internal const string AWSBucketNameKey = "AWS:BucketName"; + internal const string AWSAccountIdKey = "AWS:AccountId"; } } diff --git a/src/AzureIoTHub.Portal.Infrastructure/DevelopmentConfigHandler.cs b/src/AzureIoTHub.Portal.Infrastructure/DevelopmentConfigHandler.cs index 1581123d9..0360bff0c 100644 --- a/src/AzureIoTHub.Portal.Infrastructure/DevelopmentConfigHandler.cs +++ b/src/AzureIoTHub.Portal.Infrastructure/DevelopmentConfigHandler.cs @@ -89,5 +89,6 @@ internal DevelopmentConfigHandler(IConfiguration config) public override string AWSRegion => this.config[AWSRegionKey]!; public override string AWSS3StorageConnectionString => this.config[AWSS3StorageConnectionStringKey]!; public override string AWSBucketName => this.config[AWSBucketNameKey]!; + public override string AWSAccountId => this.config[AWSAccountIdKey]!; } } diff --git a/src/AzureIoTHub.Portal.Infrastructure/ProductionAWSConfigHandler.cs b/src/AzureIoTHub.Portal.Infrastructure/ProductionAWSConfigHandler.cs index 7e378a9c6..02966e67e 100644 --- a/src/AzureIoTHub.Portal.Infrastructure/ProductionAWSConfigHandler.cs +++ b/src/AzureIoTHub.Portal.Infrastructure/ProductionAWSConfigHandler.cs @@ -89,5 +89,7 @@ internal ProductionAWSConfigHandler(IConfiguration config) public override string AWSRegion => this.config[AWSRegionKey]!; public override string AWSS3StorageConnectionString => this.config[AWSS3StorageConnectionStringKey]!; public override string AWSBucketName => this.config[AWSBucketNameKey]!; + public override string AWSAccountId => this.config[AWSAccountIdKey]!; + } } diff --git a/src/AzureIoTHub.Portal.Infrastructure/ProductionAzureConfigHandler.cs b/src/AzureIoTHub.Portal.Infrastructure/ProductionAzureConfigHandler.cs index 8aba668b6..052d7670a 100644 --- a/src/AzureIoTHub.Portal.Infrastructure/ProductionAzureConfigHandler.cs +++ b/src/AzureIoTHub.Portal.Infrastructure/ProductionAzureConfigHandler.cs @@ -92,5 +92,7 @@ internal ProductionAzureConfigHandler(IConfiguration config) public override string AWSS3StorageConnectionString => throw new NotImplementedException(); public override string AWSBucketName => throw new NotImplementedException(); + public override string AWSAccountId => throw new NotImplementedException(); + } } diff --git a/src/AzureIoTHub.Portal.Infrastructure/Services/AWS/AwsConfigService.cs b/src/AzureIoTHub.Portal.Infrastructure/Services/AWS/AwsConfigService.cs index cefd2231d..dfc83a7e3 100644 --- a/src/AzureIoTHub.Portal.Infrastructure/Services/AWS/AwsConfigService.cs +++ b/src/AzureIoTHub.Portal.Infrastructure/Services/AWS/AwsConfigService.cs @@ -11,8 +11,13 @@ namespace AzureIoTHub.Portal.Infrastructure.Services.AWS using Amazon.GreengrassV2.Model; using Amazon.IoT; using Amazon.IoT.Model; + using AutoMapper; + using AzureIoTHub.Portal.Application.Managers; using AzureIoTHub.Portal.Application.Services; + using AzureIoTHub.Portal.Domain; + using AzureIoTHub.Portal.Domain.Entities; using AzureIoTHub.Portal.Domain.Exceptions; + using AzureIoTHub.Portal.Domain.Repositories; using AzureIoTHub.Portal.Models.v10; using AzureIoTHub.Portal.Shared.Models.v10; using Newtonsoft.Json.Linq; @@ -22,17 +27,37 @@ public class AwsConfigService : IConfigService { private readonly IAmazonGreengrassV2 greengras; private readonly IAmazonIoT iotClient; + private readonly IDeviceModelImageManager deviceModelImageManager; + + private readonly IUnitOfWork unitOfWork; + private readonly IEdgeDeviceModelRepository edgeModelRepository; + private readonly ILabelRepository labelRepository; + private readonly ConfigHandler config; + private readonly IMapper mapper; public AwsConfigService( IAmazonGreengrassV2 greengras, - IAmazonIoT iotClient) + IAmazonIoT iot, + IMapper mapper, + IUnitOfWork unitOfWork, + IEdgeDeviceModelRepository edgeModelRepository, + IDeviceModelImageManager deviceModelImageManager, + ILabelRepository labelRepository, + ConfigHandler config) { this.greengras = greengras; - this.iotClient = iotClient; + this.iotClient = iot; + this.mapper = mapper; + this.unitOfWork = unitOfWork; + this.edgeModelRepository = edgeModelRepository; + this.deviceModelImageManager = deviceModelImageManager; + this.labelRepository = labelRepository; + this.config = config; } public async Task RollOutEdgeModelConfiguration(IoTEdgeModel edgeModel) { + var createDeploymentRequest = new CreateDeploymentRequest { DeploymentName = edgeModel?.Name, @@ -47,6 +72,25 @@ public async Task RollOutEdgeModelConfiguration(IoTEdgeModel edgeModel) throw new InternalServerErrorException("The deployment creation failed due to an error in the Amazon IoT API."); } + else + { + var edgeModelEntity = await this.edgeModelRepository.GetByIdAsync(edgeModel?.ModelId); + if (edgeModelEntity == null) + { + edgeModel.ModelId = createDeploymentResponse.DeploymentId; + + edgeModelEntity = this.mapper.Map(edgeModel); + + await this.edgeModelRepository.InsertAsync(edgeModelEntity); + await this.unitOfWork.SaveAsync(); + } + else + { + throw new Domain.Exceptions.ResourceAlreadyExistsException($"The edge model with id {edgeModel?.ModelId} already exists"); + } + + _ = await this.deviceModelImageManager.SetDefaultImageToModel(edgeModel?.ModelId); + } } private async Task GetThingGroupArn(IoTEdgeModel edgeModel) @@ -118,6 +162,7 @@ private async Task> CreateG InlineRecipe = recipeStream }; var response = await greengras.CreateComponentVersionAsync(componentVersion); + if (response.HttpStatusCode != System.Net.HttpStatusCode.Created) { throw new InternalServerErrorException("The component creation failed due to an error in the Amazon IoT API."); @@ -214,10 +259,72 @@ public Task GetFailedDeploymentsCount() throw new NotImplementedException(); } - public Task> GetConfigModuleList(string modelId) + public async Task> GetConfigModuleList(string modelId) { - // To be implemented with the update method in EdgeModelService - throw new NotImplementedException(); + + var moduleList = new List(); + + var getDeployement = new GetDeploymentRequest + { + DeploymentId = modelId, + }; + try + { + var response = await this.greengras.GetDeploymentAsync(getDeployement); + + foreach (var compoenent in response.Components) + { + var responseComponent = await this.greengras.GetComponentAsync(new GetComponentRequest + { + Arn = $"arn:aws:greengrass:{config.AWSRegion}:{config.AWSAccountId}:components:{compoenent.Key}:versions:{compoenent.Value.ComponentVersion}", + RecipeOutputFormat = RecipeOutputFormat.JSON + }); + + using var reader = new StreamReader(responseComponent.Recipe); + + // Extract the lifecycle from the JSON object + var run_variable = retreiveParentAttribute("Lifecycle", "Run", reader); + + // Use the `lifecycle` variable as needed + } + return moduleList; + } + catch (Amazon.IoT.Model.ResourceNotFoundException) + { + throw new InternalServerErrorException("The deployment is not found"); + + } + } + + private static string retreiveParentAttribute(string parent, string child, StreamReader reader) + { + var recipeJsonString = reader.ReadToEnd(); + var runValue = ""; + // Parse the string as a JSON object + var recipeJsonObject = JObject.Parse(recipeJsonString); + + // Extract the "Manifests" array + var jArray = recipeJsonObject["Manifests"] as JArray; + var manifests = jArray; + + if (manifests != null && manifests.Count > 0) + { + // Get the first manifest in the array + var firstManifest = manifests[0] as JObject; + + // Extract the "Lifecycle" object + var jObject = firstManifest?[parent] as JObject; + var lifecycle = jObject; + + if (lifecycle != null) + { + // Extract the value of "Run" + runValue = lifecycle[child]?.ToString(); + + // Use the `runValue` variable as needed + } + } + return runValue; } public Task> GetModelSystemModule(string modelId) diff --git a/src/AzureIoTHub.Portal.Infrastructure/Services/EdgeModelService.cs b/src/AzureIoTHub.Portal.Infrastructure/Services/EdgeModelService.cs index 83fe5de22..4b9c038f4 100644 --- a/src/AzureIoTHub.Portal.Infrastructure/Services/EdgeModelService.cs +++ b/src/AzureIoTHub.Portal.Infrastructure/Services/EdgeModelService.cs @@ -103,25 +103,30 @@ public async Task> GetEdgeModels(EdgeModelFilt /// public async Task CreateEdgeModel(IoTEdgeModel edgeModel) { - var edgeModelEntity = await this.edgeModelRepository.GetByIdAsync(edgeModel?.ModelId); - if (edgeModelEntity == null) + if (this.config.CloudProvider.Equals(CloudProviders.Azure, StringComparison.Ordinal)) { - edgeModelEntity = this.mapper.Map(edgeModel); - await this.edgeModelRepository.InsertAsync(edgeModelEntity); - await this.unitOfWork.SaveAsync(); + var edgeModelEntity = await this.edgeModelRepository.GetByIdAsync(edgeModel?.ModelId); + if (edgeModelEntity == null) + { + edgeModelEntity = this.mapper.Map(edgeModel); + await this.edgeModelRepository.InsertAsync(edgeModelEntity); + await this.unitOfWork.SaveAsync(); + } + else + { + throw new ResourceAlreadyExistsException($"The edge model with id {edgeModel?.ModelId} already exists"); + } + + _ = await this.deviceModelImageManager.SetDefaultImageToModel(edgeModel?.ModelId); + + await SaveModuleCommands(edgeModel); + await this.configService.RollOutEdgeModelConfiguration(edgeModel); } else { - throw new ResourceAlreadyExistsException($"The edge model with id {edgeModel?.ModelId} already exists"); + await this.configService.RollOutEdgeModelConfiguration(edgeModel); } - _ = await this.deviceModelImageManager.SetDefaultImageToModel(edgeModel?.ModelId); - - if (this.config.CloudProvider.Equals(CloudProviders.Azure, StringComparison.Ordinal)) - { - await SaveModuleCommands(edgeModel); - } - await this.configService.RollOutEdgeModelConfiguration(edgeModel); } /// @@ -171,20 +176,20 @@ public async Task GetEdgeModel(string modelId) } if (config.CloudProvider.Equals(CloudProviders.Azure, StringComparison.OrdinalIgnoreCase)) { - return await GetAzureEdgeModel(modelId, edgeModelEntity); + return await GetAzureEdgeModel(edgeModelEntity); } else { - return await GetAwsEdgeModel(modelId, edgeModelEntity); + return await GetAwsEdgeModel(edgeModelEntity); } } - private async Task GetAzureEdgeModel(string modelId, EdgeDeviceModel edgeModelEntity) + private async Task GetAzureEdgeModel(EdgeDeviceModel edgeModelEntity) { - var modules = await this.configService.GetConfigModuleList(modelId); - var sysModules = await this.configService.GetModelSystemModule(modelId); - var routes = await this.configService.GetConfigRouteList(modelId); - var commands = this.commandRepository.GetAll().Where(x => x.EdgeDeviceModelId == modelId).ToList(); + var modules = await this.configService.GetConfigModuleList(edgeModelEntity.Id); + var sysModules = await this.configService.GetModelSystemModule(edgeModelEntity.Id); + var routes = await this.configService.GetConfigRouteList(edgeModelEntity.Id); + var commands = this.commandRepository.GetAll().Where(x => x.EdgeDeviceModelId == edgeModelEntity.Id).ToList(); //TODO : User a mapper //Previously return this.edgeDeviceModelMapper.CreateEdgeDeviceModel(query.Value, modules, routes, commands); @@ -214,9 +219,9 @@ private async Task GetAzureEdgeModel(string modelId, EdgeDeviceMod return result; } - private async Task GetAwsEdgeModel(string modelId, EdgeDeviceModel edgeModelEntity) + private async Task GetAwsEdgeModel(EdgeDeviceModel edgeModelEntity) { - var modules = await this.configService.GetConfigModuleList(modelId); + var modules = await this.configService.GetConfigModuleList(edgeModelEntity.Id); //TODO : User a mapper //Previously return this.edgeDeviceModelMapper.CreateEdgeDeviceModel(query.Value, modules, routes, commands); var result = new IoTEdgeModel From b12a54b3b0e1d5abc2dc8e8c1f765aa4f038a0b1 Mon Sep 17 00:00:00 2001 From: ssgueye2 Date: Thu, 25 May 2023 11:55:35 +0200 Subject: [PATCH 2/5] Update creation Deployment method + Get Deployment method --- .../Entities/EdgeDeviceModel.cs | 1 + .../Services/AWS/AwsConfigService.cs | 113 ++- .../Services/EdgeModelService.cs | 36 +- ...525074805_Add Aws DeploymentId.Designer.cs | 590 ++++++++++++++ .../20230525074805_Add Aws DeploymentId.cs | 28 + .../PortalDbContextModelSnapshot.cs | 745 +++++++++--------- .../Models/v1.0/IoTEdgeModelListItem.cs | 6 + 7 files changed, 1104 insertions(+), 415 deletions(-) create mode 100644 src/AzureIoTHub.Portal.Postgres/Migrations/20230525074805_Add Aws DeploymentId.Designer.cs create mode 100644 src/AzureIoTHub.Portal.Postgres/Migrations/20230525074805_Add Aws DeploymentId.cs diff --git a/src/AzureIoTHub.Portal.Domain/Entities/EdgeDeviceModel.cs b/src/AzureIoTHub.Portal.Domain/Entities/EdgeDeviceModel.cs index 12b29c723..2c9978eaf 100644 --- a/src/AzureIoTHub.Portal.Domain/Entities/EdgeDeviceModel.cs +++ b/src/AzureIoTHub.Portal.Domain/Entities/EdgeDeviceModel.cs @@ -10,6 +10,7 @@ public class EdgeDeviceModel : EntityBase public string Name { get; set; } = default!; public string? Description { get; set; } + public string? IdProvider { get; set; } /// /// Labels diff --git a/src/AzureIoTHub.Portal.Infrastructure/Services/AWS/AwsConfigService.cs b/src/AzureIoTHub.Portal.Infrastructure/Services/AWS/AwsConfigService.cs index dfc83a7e3..e4374d888 100644 --- a/src/AzureIoTHub.Portal.Infrastructure/Services/AWS/AwsConfigService.cs +++ b/src/AzureIoTHub.Portal.Infrastructure/Services/AWS/AwsConfigService.cs @@ -15,7 +15,6 @@ namespace AzureIoTHub.Portal.Infrastructure.Services.AWS using AzureIoTHub.Portal.Application.Managers; using AzureIoTHub.Portal.Application.Services; using AzureIoTHub.Portal.Domain; - using AzureIoTHub.Portal.Domain.Entities; using AzureIoTHub.Portal.Domain.Exceptions; using AzureIoTHub.Portal.Domain.Repositories; using AzureIoTHub.Portal.Models.v10; @@ -27,11 +26,9 @@ public class AwsConfigService : IConfigService { private readonly IAmazonGreengrassV2 greengras; private readonly IAmazonIoT iotClient; - private readonly IDeviceModelImageManager deviceModelImageManager; private readonly IUnitOfWork unitOfWork; private readonly IEdgeDeviceModelRepository edgeModelRepository; - private readonly ILabelRepository labelRepository; private readonly ConfigHandler config; private readonly IMapper mapper; @@ -41,8 +38,6 @@ public AwsConfigService( IMapper mapper, IUnitOfWork unitOfWork, IEdgeDeviceModelRepository edgeModelRepository, - IDeviceModelImageManager deviceModelImageManager, - ILabelRepository labelRepository, ConfigHandler config) { this.greengras = greengras; @@ -50,8 +45,6 @@ public AwsConfigService( this.mapper = mapper; this.unitOfWork = unitOfWork; this.edgeModelRepository = edgeModelRepository; - this.deviceModelImageManager = deviceModelImageManager; - this.labelRepository = labelRepository; this.config = config; } @@ -74,22 +67,22 @@ public async Task RollOutEdgeModelConfiguration(IoTEdgeModel edgeModel) } else { - var edgeModelEntity = await this.edgeModelRepository.GetByIdAsync(edgeModel?.ModelId); + var edgeModelEntity = await this.edgeModelRepository.GetByIdAsync(edgeModel?.ModelId!); if (edgeModelEntity == null) { - edgeModel.ModelId = createDeploymentResponse.DeploymentId; + throw new Domain.Exceptions.ResourceNotFoundException($"The edge model with id {edgeModel?.ModelId} not found"); - edgeModelEntity = this.mapper.Map(edgeModel); - - await this.edgeModelRepository.InsertAsync(edgeModelEntity); - await this.unitOfWork.SaveAsync(); } else { - throw new Domain.Exceptions.ResourceAlreadyExistsException($"The edge model with id {edgeModel?.ModelId} already exists"); + edgeModel!.IdProvider = createDeploymentResponse.DeploymentId; + + _ = this.mapper.Map(edgeModel, edgeModelEntity); + + this.edgeModelRepository.Update(edgeModelEntity); + await this.unitOfWork.SaveAsync(); } - _ = await this.deviceModelImageManager.SetDefaultImageToModel(edgeModel?.ModelId); } } @@ -163,7 +156,7 @@ private async Task> CreateG }; var response = await greengras.CreateComponentVersionAsync(componentVersion); - if (response.HttpStatusCode != System.Net.HttpStatusCode.Created) + if (response.HttpStatusCode != HttpStatusCode.Created) { throw new InternalServerErrorException("The component creation failed due to an error in the Amazon IoT API."); @@ -280,12 +273,24 @@ public async Task> GetConfigModuleList(string modelId) RecipeOutputFormat = RecipeOutputFormat.JSON }); + // Read the Recipe which is in JSON Format using var reader = new StreamReader(responseComponent.Recipe); + var recipeJsonString = reader.ReadToEnd(); + + // Extract the imageUri from the 'Run' JSON object + var uriImage = retreiveImageUri("Lifecycle", "Run", recipeJsonString); + // Extract the environment Variables from the 'Environment' JSON object + var env = retreiveEnvVariableAttr("Lifecycle", "Environment", recipeJsonString); - // Extract the lifecycle from the JSON object - var run_variable = retreiveParentAttribute("Lifecycle", "Run", reader); + var iotEdgeModule = new IoTEdgeModule + { + ModuleName = compoenent.Key, + ImageURI = uriImage, + EnvironmentVariables = env + }; + + moduleList.Add(iotEdgeModule); - // Use the `lifecycle` variable as needed } return moduleList; } @@ -296,10 +301,9 @@ public async Task> GetConfigModuleList(string modelId) } } - private static string retreiveParentAttribute(string parent, string child, StreamReader reader) + private static string retreiveImageUri(string parent, string child, string recipeJsonString) { - var recipeJsonString = reader.ReadToEnd(); - var runValue = ""; + var uriImage = ""; // Parse the string as a JSON object var recipeJsonObject = JObject.Parse(recipeJsonString); @@ -319,12 +323,71 @@ private static string retreiveParentAttribute(string parent, string child, Strea if (lifecycle != null) { // Extract the value of "Run" - runValue = lifecycle[child]?.ToString(); + var runValue = lifecycle[child]?.ToString(); + + // Search the index of the 1st whitespace + var firstSpaceIndex = runValue.IndexOf(' '); + + if (firstSpaceIndex != -1) + { + // // Search the index of the 2nd whitespace + var secondSpaceIndex = runValue.IndexOf(' ', firstSpaceIndex + 1); + + if (secondSpaceIndex != -1) + { + // Extract the URI iamge + uriImage = runValue[(secondSpaceIndex + 1)..]; + } + + } + } + } - // Use the `runValue` variable as needed + return uriImage; + } + + private static List retreiveEnvVariableAttr(string parent, string child, string recipeJsonString) + { + + // Parse the string as a JSON object + var recipeJsonObject = JObject.Parse(recipeJsonString); + + var environmentVariables = new List(); + + // Extract the "Manifests" array + var jArray = recipeJsonObject["Manifests"] as JArray; + var manifests = jArray; + + if (manifests != null && manifests.Count > 0) + { + // Get the first manifest in the array + var firstManifest = manifests[0] as JObject; + + // Extract the "Lifecycle" object + var jObject = firstManifest?[parent] as JObject; + var lifecycle = jObject; + + if (lifecycle != null) + { + // Extract the value of "Environment" + var env = lifecycle?[child] as JObject; + + // Convert Environment JSON Object as a dictionnary + var keyValuePairs = env!.ToObject>(); + + foreach (var kvp in keyValuePairs!) + { + var iotEnvVariable = new IoTEdgeModuleEnvironmentVariable + { + Name = kvp.Key, + Value = kvp.Value + }; + + environmentVariables.Add(iotEnvVariable); + } } } - return runValue; + return environmentVariables; } public Task> GetModelSystemModule(string modelId) diff --git a/src/AzureIoTHub.Portal.Infrastructure/Services/EdgeModelService.cs b/src/AzureIoTHub.Portal.Infrastructure/Services/EdgeModelService.cs index 4b9c038f4..e88fa790b 100644 --- a/src/AzureIoTHub.Portal.Infrastructure/Services/EdgeModelService.cs +++ b/src/AzureIoTHub.Portal.Infrastructure/Services/EdgeModelService.cs @@ -103,30 +103,28 @@ public async Task> GetEdgeModels(EdgeModelFilt /// public async Task CreateEdgeModel(IoTEdgeModel edgeModel) { - if (this.config.CloudProvider.Equals(CloudProviders.Azure, StringComparison.Ordinal)) + var edgeModelEntity = await this.edgeModelRepository.GetByIdAsync(edgeModel?.ModelId); + if (edgeModelEntity == null) { - var edgeModelEntity = await this.edgeModelRepository.GetByIdAsync(edgeModel?.ModelId); - if (edgeModelEntity == null) - { - edgeModelEntity = this.mapper.Map(edgeModel); - await this.edgeModelRepository.InsertAsync(edgeModelEntity); - await this.unitOfWork.SaveAsync(); - } - else - { - throw new ResourceAlreadyExistsException($"The edge model with id {edgeModel?.ModelId} already exists"); - } - - _ = await this.deviceModelImageManager.SetDefaultImageToModel(edgeModel?.ModelId); - - await SaveModuleCommands(edgeModel); - await this.configService.RollOutEdgeModelConfiguration(edgeModel); + edgeModelEntity = this.mapper.Map(edgeModel); + await this.edgeModelRepository.InsertAsync(edgeModelEntity); + await this.unitOfWork.SaveAsync(); } else { - await this.configService.RollOutEdgeModelConfiguration(edgeModel); + throw new ResourceAlreadyExistsException($"The edge model with id {edgeModel?.ModelId} already exists"); } + _ = await this.deviceModelImageManager.SetDefaultImageToModel(edgeModel?.ModelId); + + + if (this.config.CloudProvider.Equals(CloudProviders.Azure, StringComparison.Ordinal)) + { + await SaveModuleCommands(edgeModel); + } + + await this.configService.RollOutEdgeModelConfiguration(edgeModel); + } /// @@ -221,7 +219,7 @@ private async Task GetAzureEdgeModel(EdgeDeviceModel edgeModelEnti private async Task GetAwsEdgeModel(EdgeDeviceModel edgeModelEntity) { - var modules = await this.configService.GetConfigModuleList(edgeModelEntity.Id); + var modules = await this.configService.GetConfigModuleList(edgeModelEntity.IdProvider!); //TODO : User a mapper //Previously return this.edgeDeviceModelMapper.CreateEdgeDeviceModel(query.Value, modules, routes, commands); var result = new IoTEdgeModel diff --git a/src/AzureIoTHub.Portal.Postgres/Migrations/20230525074805_Add Aws DeploymentId.Designer.cs b/src/AzureIoTHub.Portal.Postgres/Migrations/20230525074805_Add Aws DeploymentId.Designer.cs new file mode 100644 index 000000000..64895a388 --- /dev/null +++ b/src/AzureIoTHub.Portal.Postgres/Migrations/20230525074805_Add Aws DeploymentId.Designer.cs @@ -0,0 +1,590 @@ +// +using System; +using AzureIoTHub.Portal.Infrastructure; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata; + +#nullable disable + +namespace AzureIoTHub.Portal.Postgres.Migrations +{ + [DbContext(typeof(PortalDbContext))] + [Migration("20230525074805_Add Aws DeploymentId")] + partial class AddAwsDeploymentId + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "7.0.4") + .HasAnnotation("Relational:MaxIdentifierLength", 63); + + NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); + + modelBuilder.Entity("AzureIoTHub.Portal.Domain.Entities.Concentrator", b => + { + b.Property("Id") + .HasColumnType("text"); + + b.Property("ClientThumbprint") + .HasColumnType("text"); + + b.Property("DeviceType") + .IsRequired() + .HasColumnType("text"); + + b.Property("IsConnected") + .HasColumnType("boolean"); + + b.Property("IsEnabled") + .HasColumnType("boolean"); + + b.Property("LoraRegion") + .IsRequired() + .HasColumnType("text"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.Property("Version") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.ToTable("Concentrators"); + }); + + modelBuilder.Entity("AzureIoTHub.Portal.Domain.Entities.Device", b => + { + b.Property("Id") + .HasColumnType("text"); + + b.Property("DeviceModelId") + .IsRequired() + .HasColumnType("text"); + + b.Property("IsConnected") + .HasColumnType("boolean"); + + b.Property("IsEnabled") + .HasColumnType("boolean"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.Property("StatusUpdatedTime") + .HasColumnType("timestamp with time zone"); + + b.Property("Version") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.HasIndex("DeviceModelId"); + + b.ToTable("Devices", (string)null); + + b.UseTptMappingStrategy(); + }); + + modelBuilder.Entity("AzureIoTHub.Portal.Domain.Entities.DeviceModel", b => + { + b.Property("Id") + .HasColumnType("text"); + + b.Property("ABPRelaxMode") + .HasColumnType("boolean"); + + b.Property("AppEUI") + .HasColumnType("text"); + + b.Property("ClassType") + .HasColumnType("integer"); + + b.Property("Deduplication") + .HasColumnType("integer"); + + b.Property("Description") + .HasColumnType("text"); + + b.Property("Downlink") + .HasColumnType("boolean"); + + b.Property("IsBuiltin") + .HasColumnType("boolean"); + + b.Property("KeepAliveTimeout") + .HasColumnType("integer"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.Property("PreferredWindow") + .HasColumnType("integer"); + + b.Property("RXDelay") + .HasColumnType("integer"); + + b.Property("SensorDecoder") + .HasColumnType("text"); + + b.Property("SupportLoRaFeatures") + .HasColumnType("boolean"); + + b.Property("UseOTAA") + .HasColumnType("boolean"); + + b.HasKey("Id"); + + b.ToTable("DeviceModels"); + }); + + modelBuilder.Entity("AzureIoTHub.Portal.Domain.Entities.DeviceModelCommand", b => + { + b.Property("Id") + .HasColumnType("text"); + + b.Property("Confirmed") + .HasColumnType("boolean"); + + b.Property("DeviceModelId") + .IsRequired() + .HasColumnType("text"); + + b.Property("Frame") + .IsRequired() + .HasColumnType("text"); + + b.Property("IsBuiltin") + .HasColumnType("boolean"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.Property("Port") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.ToTable("DeviceModelCommands"); + }); + + modelBuilder.Entity("AzureIoTHub.Portal.Domain.Entities.DeviceModelProperty", b => + { + b.Property("Id") + .HasColumnType("text"); + + b.Property("DisplayName") + .IsRequired() + .HasColumnType("text"); + + b.Property("IsWritable") + .HasColumnType("boolean"); + + b.Property("ModelId") + .IsRequired() + .HasColumnType("text"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.Property("Order") + .HasColumnType("integer"); + + b.Property("PropertyType") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.ToTable("DeviceModelProperties"); + }); + + modelBuilder.Entity("AzureIoTHub.Portal.Domain.Entities.DeviceTag", b => + { + b.Property("Id") + .HasColumnType("text"); + + b.Property("Label") + .IsRequired() + .HasColumnType("text"); + + b.Property("Required") + .HasColumnType("boolean"); + + b.Property("Searchable") + .HasColumnType("boolean"); + + b.HasKey("Id"); + + b.ToTable("DeviceTags"); + }); + + modelBuilder.Entity("AzureIoTHub.Portal.Domain.Entities.DeviceTagValue", b => + { + b.Property("Id") + .HasColumnType("text"); + + b.Property("DeviceId") + .HasColumnType("text"); + + b.Property("EdgeDeviceId") + .HasColumnType("text"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.Property("Value") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("DeviceId"); + + b.HasIndex("EdgeDeviceId"); + + b.ToTable("DeviceTagValues"); + }); + + modelBuilder.Entity("AzureIoTHub.Portal.Domain.Entities.EdgeDevice", b => + { + b.Property("Id") + .HasColumnType("text"); + + b.Property("ConnectionState") + .IsRequired() + .HasColumnType("text"); + + b.Property("DeviceModelId") + .IsRequired() + .HasColumnType("text"); + + b.Property("IsEnabled") + .HasColumnType("boolean"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.Property("NbDevices") + .HasColumnType("integer"); + + b.Property("NbModules") + .HasColumnType("integer"); + + b.Property("Scope") + .HasColumnType("text"); + + b.Property("Version") + .HasColumnType("integer"); + + b.HasKey("Id"); + + b.HasIndex("DeviceModelId"); + + b.ToTable("EdgeDevices"); + }); + + modelBuilder.Entity("AzureIoTHub.Portal.Domain.Entities.EdgeDeviceModel", b => + { + b.Property("Id") + .HasColumnType("text"); + + b.Property("Description") + .HasColumnType("text"); + + b.Property("IdProvider") + .HasColumnType("text"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.ToTable("EdgeDeviceModels"); + }); + + modelBuilder.Entity("AzureIoTHub.Portal.Domain.Entities.EdgeDeviceModelCommand", b => + { + b.Property("Id") + .HasColumnType("text"); + + b.Property("EdgeDeviceModelId") + .IsRequired() + .HasColumnType("text"); + + b.Property("ModuleName") + .IsRequired() + .HasColumnType("text"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.ToTable("EdgeDeviceModelCommands"); + }); + + modelBuilder.Entity("AzureIoTHub.Portal.Domain.Entities.Label", b => + { + b.Property("Id") + .HasColumnType("text"); + + b.Property("Color") + .IsRequired() + .HasColumnType("text"); + + b.Property("DeviceId") + .HasColumnType("text"); + + b.Property("DeviceModelId") + .HasColumnType("text"); + + b.Property("EdgeDeviceId") + .HasColumnType("text"); + + b.Property("EdgeDeviceModelId") + .HasColumnType("text"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("DeviceId"); + + b.HasIndex("DeviceModelId"); + + b.HasIndex("EdgeDeviceId"); + + b.HasIndex("EdgeDeviceModelId"); + + b.ToTable("Labels"); + }); + + modelBuilder.Entity("AzureIoTHub.Portal.Domain.Entities.LoRaDeviceTelemetry", b => + { + b.Property("Id") + .HasColumnType("text"); + + b.Property("EnqueuedTime") + .HasColumnType("timestamp with time zone"); + + b.Property("LorawanDeviceId") + .HasColumnType("text"); + + b.Property("Telemetry") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("LorawanDeviceId"); + + b.ToTable("LoRaDeviceTelemetry"); + }); + + modelBuilder.Entity("AzureIoTHub.Portal.Domain.Entities.LorawanDevice", b => + { + b.HasBaseType("AzureIoTHub.Portal.Domain.Entities.Device"); + + b.Property("ABPRelaxMode") + .HasColumnType("boolean"); + + b.Property("AlreadyLoggedInOnce") + .HasColumnType("boolean"); + + b.Property("AppEUI") + .HasColumnType("text"); + + b.Property("AppKey") + .HasColumnType("text"); + + b.Property("AppSKey") + .HasColumnType("text"); + + b.Property("ClassType") + .HasColumnType("integer"); + + b.Property("DataRate") + .HasColumnType("text"); + + b.Property("Deduplication") + .HasColumnType("integer"); + + b.Property("DevAddr") + .HasColumnType("text"); + + b.Property("Downlink") + .HasColumnType("boolean"); + + b.Property("FCntDownStart") + .HasColumnType("integer"); + + b.Property("FCntResetCounter") + .HasColumnType("integer"); + + b.Property("FCntUpStart") + .HasColumnType("integer"); + + b.Property("GatewayID") + .HasColumnType("text"); + + b.Property("KeepAliveTimeout") + .HasColumnType("integer"); + + b.Property("NbRep") + .HasColumnType("text"); + + b.Property("NwkSKey") + .HasColumnType("text"); + + b.Property("PreferredWindow") + .HasColumnType("integer"); + + b.Property("RX1DROffset") + .HasColumnType("integer"); + + b.Property("RX2DataRate") + .HasColumnType("integer"); + + b.Property("RXDelay") + .HasColumnType("integer"); + + b.Property("ReportedRX1DROffset") + .HasColumnType("text"); + + b.Property("ReportedRX2DataRate") + .HasColumnType("text"); + + b.Property("ReportedRXDelay") + .HasColumnType("text"); + + b.Property("SensorDecoder") + .HasColumnType("text"); + + b.Property("Supports32BitFCnt") + .HasColumnType("boolean"); + + b.Property("TxPower") + .HasColumnType("text"); + + b.Property("UseOTAA") + .HasColumnType("boolean"); + + b.ToTable("LorawanDevices", (string)null); + }); + + modelBuilder.Entity("AzureIoTHub.Portal.Domain.Entities.Device", b => + { + b.HasOne("AzureIoTHub.Portal.Domain.Entities.DeviceModel", "DeviceModel") + .WithMany() + .HasForeignKey("DeviceModelId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("DeviceModel"); + }); + + modelBuilder.Entity("AzureIoTHub.Portal.Domain.Entities.DeviceTagValue", b => + { + b.HasOne("AzureIoTHub.Portal.Domain.Entities.Device", null) + .WithMany("Tags") + .HasForeignKey("DeviceId"); + + b.HasOne("AzureIoTHub.Portal.Domain.Entities.EdgeDevice", null) + .WithMany("Tags") + .HasForeignKey("EdgeDeviceId"); + }); + + modelBuilder.Entity("AzureIoTHub.Portal.Domain.Entities.EdgeDevice", b => + { + b.HasOne("AzureIoTHub.Portal.Domain.Entities.EdgeDeviceModel", "DeviceModel") + .WithMany() + .HasForeignKey("DeviceModelId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("DeviceModel"); + }); + + modelBuilder.Entity("AzureIoTHub.Portal.Domain.Entities.Label", b => + { + b.HasOne("AzureIoTHub.Portal.Domain.Entities.Device", null) + .WithMany("Labels") + .HasForeignKey("DeviceId"); + + b.HasOne("AzureIoTHub.Portal.Domain.Entities.DeviceModel", null) + .WithMany("Labels") + .HasForeignKey("DeviceModelId"); + + b.HasOne("AzureIoTHub.Portal.Domain.Entities.EdgeDevice", null) + .WithMany("Labels") + .HasForeignKey("EdgeDeviceId"); + + b.HasOne("AzureIoTHub.Portal.Domain.Entities.EdgeDeviceModel", null) + .WithMany("Labels") + .HasForeignKey("EdgeDeviceModelId"); + }); + + modelBuilder.Entity("AzureIoTHub.Portal.Domain.Entities.LoRaDeviceTelemetry", b => + { + b.HasOne("AzureIoTHub.Portal.Domain.Entities.LorawanDevice", null) + .WithMany("Telemetry") + .HasForeignKey("LorawanDeviceId"); + }); + + modelBuilder.Entity("AzureIoTHub.Portal.Domain.Entities.LorawanDevice", b => + { + b.HasOne("AzureIoTHub.Portal.Domain.Entities.Device", null) + .WithOne() + .HasForeignKey("AzureIoTHub.Portal.Domain.Entities.LorawanDevice", "Id") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("AzureIoTHub.Portal.Domain.Entities.Device", b => + { + b.Navigation("Labels"); + + b.Navigation("Tags"); + }); + + modelBuilder.Entity("AzureIoTHub.Portal.Domain.Entities.DeviceModel", b => + { + b.Navigation("Labels"); + }); + + modelBuilder.Entity("AzureIoTHub.Portal.Domain.Entities.EdgeDevice", b => + { + b.Navigation("Labels"); + + b.Navigation("Tags"); + }); + + modelBuilder.Entity("AzureIoTHub.Portal.Domain.Entities.EdgeDeviceModel", b => + { + b.Navigation("Labels"); + }); + + modelBuilder.Entity("AzureIoTHub.Portal.Domain.Entities.LorawanDevice", b => + { + b.Navigation("Telemetry"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/src/AzureIoTHub.Portal.Postgres/Migrations/20230525074805_Add Aws DeploymentId.cs b/src/AzureIoTHub.Portal.Postgres/Migrations/20230525074805_Add Aws DeploymentId.cs new file mode 100644 index 000000000..5cf0008c8 --- /dev/null +++ b/src/AzureIoTHub.Portal.Postgres/Migrations/20230525074805_Add Aws DeploymentId.cs @@ -0,0 +1,28 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace AzureIoTHub.Portal.Postgres.Migrations +{ + /// + public partial class AddAwsDeploymentId : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "IdProvider", + table: "EdgeDeviceModels", + type: "text", + nullable: true); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropColumn( + name: "IdProvider", + table: "EdgeDeviceModels"); + } + } +} diff --git a/src/AzureIoTHub.Portal.Postgres/Migrations/PortalDbContextModelSnapshot.cs b/src/AzureIoTHub.Portal.Postgres/Migrations/PortalDbContextModelSnapshot.cs index 2a1d1045c..05d5edac4 100644 --- a/src/AzureIoTHub.Portal.Postgres/Migrations/PortalDbContextModelSnapshot.cs +++ b/src/AzureIoTHub.Portal.Postgres/Migrations/PortalDbContextModelSnapshot.cs @@ -1,4 +1,4 @@ -// +// using System; using AzureIoTHub.Portal.Infrastructure; using Microsoft.EntityFrameworkCore; @@ -23,561 +23,564 @@ protected override void BuildModel(ModelBuilder modelBuilder) NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder); modelBuilder.Entity("AzureIoTHub.Portal.Domain.Entities.Concentrator", b => - { - b.Property("Id") - .HasColumnType("text"); + { + b.Property("Id") + .HasColumnType("text"); - b.Property("ClientThumbprint") - .HasColumnType("text"); + b.Property("ClientThumbprint") + .HasColumnType("text"); - b.Property("DeviceType") - .IsRequired() - .HasColumnType("text"); + b.Property("DeviceType") + .IsRequired() + .HasColumnType("text"); - b.Property("IsConnected") - .HasColumnType("boolean"); + b.Property("IsConnected") + .HasColumnType("boolean"); - b.Property("IsEnabled") - .HasColumnType("boolean"); + b.Property("IsEnabled") + .HasColumnType("boolean"); - b.Property("LoraRegion") - .IsRequired() - .HasColumnType("text"); + b.Property("LoraRegion") + .IsRequired() + .HasColumnType("text"); - b.Property("Name") - .IsRequired() - .HasColumnType("text"); + b.Property("Name") + .IsRequired() + .HasColumnType("text"); - b.Property("Version") - .HasColumnType("integer"); + b.Property("Version") + .HasColumnType("integer"); - b.HasKey("Id"); + b.HasKey("Id"); - b.ToTable("Concentrators"); - }); + b.ToTable("Concentrators"); + }); modelBuilder.Entity("AzureIoTHub.Portal.Domain.Entities.Device", b => - { - b.Property("Id") - .HasColumnType("text"); + { + b.Property("Id") + .HasColumnType("text"); - b.Property("DeviceModelId") - .IsRequired() - .HasColumnType("text"); + b.Property("DeviceModelId") + .IsRequired() + .HasColumnType("text"); - b.Property("IsConnected") - .HasColumnType("boolean"); + b.Property("IsConnected") + .HasColumnType("boolean"); - b.Property("IsEnabled") - .HasColumnType("boolean"); + b.Property("IsEnabled") + .HasColumnType("boolean"); - b.Property("Name") - .IsRequired() - .HasColumnType("text"); + b.Property("Name") + .IsRequired() + .HasColumnType("text"); - b.Property("StatusUpdatedTime") - .HasColumnType("timestamp with time zone"); + b.Property("StatusUpdatedTime") + .HasColumnType("timestamp with time zone"); - b.Property("Version") - .HasColumnType("integer"); + b.Property("Version") + .HasColumnType("integer"); - b.HasKey("Id"); + b.HasKey("Id"); - b.HasIndex("DeviceModelId"); + b.HasIndex("DeviceModelId"); - b.ToTable("Devices", (string)null); + b.ToTable("Devices", (string)null); - b.UseTptMappingStrategy(); - }); + b.UseTptMappingStrategy(); + }); modelBuilder.Entity("AzureIoTHub.Portal.Domain.Entities.DeviceModel", b => - { - b.Property("Id") - .HasColumnType("text"); + { + b.Property("Id") + .HasColumnType("text"); - b.Property("ABPRelaxMode") - .HasColumnType("boolean"); + b.Property("ABPRelaxMode") + .HasColumnType("boolean"); - b.Property("AppEUI") - .HasColumnType("text"); + b.Property("AppEUI") + .HasColumnType("text"); - b.Property("ClassType") - .HasColumnType("integer"); + b.Property("ClassType") + .HasColumnType("integer"); - b.Property("Deduplication") - .HasColumnType("integer"); + b.Property("Deduplication") + .HasColumnType("integer"); - b.Property("Description") - .HasColumnType("text"); + b.Property("Description") + .HasColumnType("text"); - b.Property("Downlink") - .HasColumnType("boolean"); + b.Property("Downlink") + .HasColumnType("boolean"); - b.Property("IsBuiltin") - .HasColumnType("boolean"); + b.Property("IsBuiltin") + .HasColumnType("boolean"); - b.Property("KeepAliveTimeout") - .HasColumnType("integer"); + b.Property("KeepAliveTimeout") + .HasColumnType("integer"); - b.Property("Name") - .IsRequired() - .HasColumnType("text"); + b.Property("Name") + .IsRequired() + .HasColumnType("text"); - b.Property("PreferredWindow") - .HasColumnType("integer"); + b.Property("PreferredWindow") + .HasColumnType("integer"); - b.Property("RXDelay") - .HasColumnType("integer"); + b.Property("RXDelay") + .HasColumnType("integer"); - b.Property("SensorDecoder") - .HasColumnType("text"); + b.Property("SensorDecoder") + .HasColumnType("text"); - b.Property("SupportLoRaFeatures") - .HasColumnType("boolean"); + b.Property("SupportLoRaFeatures") + .HasColumnType("boolean"); - b.Property("UseOTAA") - .HasColumnType("boolean"); + b.Property("UseOTAA") + .HasColumnType("boolean"); - b.HasKey("Id"); + b.HasKey("Id"); - b.ToTable("DeviceModels"); - }); + b.ToTable("DeviceModels"); + }); modelBuilder.Entity("AzureIoTHub.Portal.Domain.Entities.DeviceModelCommand", b => - { - b.Property("Id") - .HasColumnType("text"); + { + b.Property("Id") + .HasColumnType("text"); - b.Property("Confirmed") - .HasColumnType("boolean"); + b.Property("Confirmed") + .HasColumnType("boolean"); - b.Property("DeviceModelId") - .IsRequired() - .HasColumnType("text"); + b.Property("DeviceModelId") + .IsRequired() + .HasColumnType("text"); - b.Property("Frame") - .IsRequired() - .HasColumnType("text"); + b.Property("Frame") + .IsRequired() + .HasColumnType("text"); - b.Property("IsBuiltin") - .HasColumnType("boolean"); + b.Property("IsBuiltin") + .HasColumnType("boolean"); - b.Property("Name") - .IsRequired() - .HasColumnType("text"); + b.Property("Name") + .IsRequired() + .HasColumnType("text"); - b.Property("Port") - .HasColumnType("integer"); + b.Property("Port") + .HasColumnType("integer"); - b.HasKey("Id"); + b.HasKey("Id"); - b.ToTable("DeviceModelCommands"); - }); + b.ToTable("DeviceModelCommands"); + }); modelBuilder.Entity("AzureIoTHub.Portal.Domain.Entities.DeviceModelProperty", b => - { - b.Property("Id") - .HasColumnType("text"); + { + b.Property("Id") + .HasColumnType("text"); - b.Property("DisplayName") - .IsRequired() - .HasColumnType("text"); + b.Property("DisplayName") + .IsRequired() + .HasColumnType("text"); - b.Property("IsWritable") - .HasColumnType("boolean"); + b.Property("IsWritable") + .HasColumnType("boolean"); - b.Property("ModelId") - .IsRequired() - .HasColumnType("text"); + b.Property("ModelId") + .IsRequired() + .HasColumnType("text"); - b.Property("Name") - .IsRequired() - .HasColumnType("text"); + b.Property("Name") + .IsRequired() + .HasColumnType("text"); - b.Property("Order") - .HasColumnType("integer"); + b.Property("Order") + .HasColumnType("integer"); - b.Property("PropertyType") - .HasColumnType("integer"); + b.Property("PropertyType") + .HasColumnType("integer"); - b.HasKey("Id"); + b.HasKey("Id"); - b.ToTable("DeviceModelProperties"); - }); + b.ToTable("DeviceModelProperties"); + }); modelBuilder.Entity("AzureIoTHub.Portal.Domain.Entities.DeviceTag", b => - { - b.Property("Id") - .HasColumnType("text"); + { + b.Property("Id") + .HasColumnType("text"); - b.Property("Label") - .IsRequired() - .HasColumnType("text"); + b.Property("Label") + .IsRequired() + .HasColumnType("text"); - b.Property("Required") - .HasColumnType("boolean"); + b.Property("Required") + .HasColumnType("boolean"); - b.Property("Searchable") - .HasColumnType("boolean"); + b.Property("Searchable") + .HasColumnType("boolean"); - b.HasKey("Id"); + b.HasKey("Id"); - b.ToTable("DeviceTags"); - }); + b.ToTable("DeviceTags"); + }); modelBuilder.Entity("AzureIoTHub.Portal.Domain.Entities.DeviceTagValue", b => - { - b.Property("Id") - .HasColumnType("text"); + { + b.Property("Id") + .HasColumnType("text"); - b.Property("DeviceId") - .HasColumnType("text"); + b.Property("DeviceId") + .HasColumnType("text"); - b.Property("EdgeDeviceId") - .HasColumnType("text"); + b.Property("EdgeDeviceId") + .HasColumnType("text"); - b.Property("Name") - .IsRequired() - .HasColumnType("text"); + b.Property("Name") + .IsRequired() + .HasColumnType("text"); - b.Property("Value") - .IsRequired() - .HasColumnType("text"); + b.Property("Value") + .IsRequired() + .HasColumnType("text"); - b.HasKey("Id"); + b.HasKey("Id"); - b.HasIndex("DeviceId"); + b.HasIndex("DeviceId"); - b.HasIndex("EdgeDeviceId"); + b.HasIndex("EdgeDeviceId"); - b.ToTable("DeviceTagValues"); - }); + b.ToTable("DeviceTagValues"); + }); modelBuilder.Entity("AzureIoTHub.Portal.Domain.Entities.EdgeDevice", b => - { - b.Property("Id") - .HasColumnType("text"); + { + b.Property("Id") + .HasColumnType("text"); - b.Property("ConnectionState") - .IsRequired() - .HasColumnType("text"); + b.Property("ConnectionState") + .IsRequired() + .HasColumnType("text"); - b.Property("DeviceModelId") - .IsRequired() - .HasColumnType("text"); + b.Property("DeviceModelId") + .IsRequired() + .HasColumnType("text"); - b.Property("IsEnabled") - .HasColumnType("boolean"); + b.Property("IsEnabled") + .HasColumnType("boolean"); - b.Property("Name") - .IsRequired() - .HasColumnType("text"); + b.Property("Name") + .IsRequired() + .HasColumnType("text"); - b.Property("NbDevices") - .HasColumnType("integer"); + b.Property("NbDevices") + .HasColumnType("integer"); - b.Property("NbModules") - .HasColumnType("integer"); + b.Property("NbModules") + .HasColumnType("integer"); - b.Property("Scope") - .HasColumnType("text"); + b.Property("Scope") + .HasColumnType("text"); - b.Property("Version") - .HasColumnType("integer"); + b.Property("Version") + .HasColumnType("integer"); - b.HasKey("Id"); + b.HasKey("Id"); - b.HasIndex("DeviceModelId"); + b.HasIndex("DeviceModelId"); - b.ToTable("EdgeDevices"); - }); + b.ToTable("EdgeDevices"); + }); modelBuilder.Entity("AzureIoTHub.Portal.Domain.Entities.EdgeDeviceModel", b => - { - b.Property("Id") - .HasColumnType("text"); + { + b.Property("Id") + .HasColumnType("text"); - b.Property("Description") - .HasColumnType("text"); + b.Property("Description") + .HasColumnType("text"); - b.Property("Name") - .IsRequired() - .HasColumnType("text"); + b.Property("IdProvider") + .HasColumnType("text"); - b.HasKey("Id"); + b.Property("Name") + .IsRequired() + .HasColumnType("text"); - b.ToTable("EdgeDeviceModels"); - }); + b.HasKey("Id"); + + b.ToTable("EdgeDeviceModels"); + }); modelBuilder.Entity("AzureIoTHub.Portal.Domain.Entities.EdgeDeviceModelCommand", b => - { - b.Property("Id") - .HasColumnType("text"); + { + b.Property("Id") + .HasColumnType("text"); - b.Property("EdgeDeviceModelId") - .IsRequired() - .HasColumnType("text"); + b.Property("EdgeDeviceModelId") + .IsRequired() + .HasColumnType("text"); - b.Property("ModuleName") - .IsRequired() - .HasColumnType("text"); + b.Property("ModuleName") + .IsRequired() + .HasColumnType("text"); - b.Property("Name") - .IsRequired() - .HasColumnType("text"); + b.Property("Name") + .IsRequired() + .HasColumnType("text"); - b.HasKey("Id"); + b.HasKey("Id"); - b.ToTable("EdgeDeviceModelCommands"); - }); + b.ToTable("EdgeDeviceModelCommands"); + }); modelBuilder.Entity("AzureIoTHub.Portal.Domain.Entities.Label", b => - { - b.Property("Id") - .HasColumnType("text"); + { + b.Property("Id") + .HasColumnType("text"); - b.Property("Color") - .IsRequired() - .HasColumnType("text"); + b.Property("Color") + .IsRequired() + .HasColumnType("text"); - b.Property("DeviceId") - .HasColumnType("text"); + b.Property("DeviceId") + .HasColumnType("text"); - b.Property("DeviceModelId") - .HasColumnType("text"); + b.Property("DeviceModelId") + .HasColumnType("text"); - b.Property("EdgeDeviceId") - .HasColumnType("text"); + b.Property("EdgeDeviceId") + .HasColumnType("text"); - b.Property("EdgeDeviceModelId") - .HasColumnType("text"); + b.Property("EdgeDeviceModelId") + .HasColumnType("text"); - b.Property("Name") - .IsRequired() - .HasColumnType("text"); + b.Property("Name") + .IsRequired() + .HasColumnType("text"); - b.HasKey("Id"); + b.HasKey("Id"); - b.HasIndex("DeviceId"); + b.HasIndex("DeviceId"); - b.HasIndex("DeviceModelId"); + b.HasIndex("DeviceModelId"); - b.HasIndex("EdgeDeviceId"); + b.HasIndex("EdgeDeviceId"); - b.HasIndex("EdgeDeviceModelId"); + b.HasIndex("EdgeDeviceModelId"); - b.ToTable("Labels"); - }); + b.ToTable("Labels"); + }); modelBuilder.Entity("AzureIoTHub.Portal.Domain.Entities.LoRaDeviceTelemetry", b => - { - b.Property("Id") - .HasColumnType("text"); + { + b.Property("Id") + .HasColumnType("text"); - b.Property("EnqueuedTime") - .HasColumnType("timestamp with time zone"); + b.Property("EnqueuedTime") + .HasColumnType("timestamp with time zone"); - b.Property("LorawanDeviceId") - .HasColumnType("text"); + b.Property("LorawanDeviceId") + .HasColumnType("text"); - b.Property("Telemetry") - .IsRequired() - .HasColumnType("text"); + b.Property("Telemetry") + .IsRequired() + .HasColumnType("text"); - b.HasKey("Id"); + b.HasKey("Id"); - b.HasIndex("LorawanDeviceId"); + b.HasIndex("LorawanDeviceId"); - b.ToTable("LoRaDeviceTelemetry"); - }); + b.ToTable("LoRaDeviceTelemetry"); + }); modelBuilder.Entity("AzureIoTHub.Portal.Domain.Entities.LorawanDevice", b => - { - b.HasBaseType("AzureIoTHub.Portal.Domain.Entities.Device"); + { + b.HasBaseType("AzureIoTHub.Portal.Domain.Entities.Device"); - b.Property("ABPRelaxMode") - .HasColumnType("boolean"); + b.Property("ABPRelaxMode") + .HasColumnType("boolean"); - b.Property("AlreadyLoggedInOnce") - .HasColumnType("boolean"); + b.Property("AlreadyLoggedInOnce") + .HasColumnType("boolean"); - b.Property("AppEUI") - .HasColumnType("text"); + b.Property("AppEUI") + .HasColumnType("text"); - b.Property("AppKey") - .HasColumnType("text"); + b.Property("AppKey") + .HasColumnType("text"); - b.Property("AppSKey") - .HasColumnType("text"); + b.Property("AppSKey") + .HasColumnType("text"); - b.Property("ClassType") - .HasColumnType("integer"); + b.Property("ClassType") + .HasColumnType("integer"); - b.Property("DataRate") - .HasColumnType("text"); + b.Property("DataRate") + .HasColumnType("text"); - b.Property("Deduplication") - .HasColumnType("integer"); + b.Property("Deduplication") + .HasColumnType("integer"); - b.Property("DevAddr") - .HasColumnType("text"); + b.Property("DevAddr") + .HasColumnType("text"); - b.Property("Downlink") - .HasColumnType("boolean"); + b.Property("Downlink") + .HasColumnType("boolean"); - b.Property("FCntDownStart") - .HasColumnType("integer"); + b.Property("FCntDownStart") + .HasColumnType("integer"); - b.Property("FCntResetCounter") - .HasColumnType("integer"); + b.Property("FCntResetCounter") + .HasColumnType("integer"); - b.Property("FCntUpStart") - .HasColumnType("integer"); + b.Property("FCntUpStart") + .HasColumnType("integer"); - b.Property("GatewayID") - .HasColumnType("text"); + b.Property("GatewayID") + .HasColumnType("text"); - b.Property("KeepAliveTimeout") - .HasColumnType("integer"); + b.Property("KeepAliveTimeout") + .HasColumnType("integer"); - b.Property("NbRep") - .HasColumnType("text"); + b.Property("NbRep") + .HasColumnType("text"); - b.Property("NwkSKey") - .HasColumnType("text"); + b.Property("NwkSKey") + .HasColumnType("text"); - b.Property("PreferredWindow") - .HasColumnType("integer"); + b.Property("PreferredWindow") + .HasColumnType("integer"); - b.Property("RX1DROffset") - .HasColumnType("integer"); + b.Property("RX1DROffset") + .HasColumnType("integer"); - b.Property("RX2DataRate") - .HasColumnType("integer"); + b.Property("RX2DataRate") + .HasColumnType("integer"); - b.Property("RXDelay") - .HasColumnType("integer"); + b.Property("RXDelay") + .HasColumnType("integer"); - b.Property("ReportedRX1DROffset") - .HasColumnType("text"); + b.Property("ReportedRX1DROffset") + .HasColumnType("text"); - b.Property("ReportedRX2DataRate") - .HasColumnType("text"); + b.Property("ReportedRX2DataRate") + .HasColumnType("text"); - b.Property("ReportedRXDelay") - .HasColumnType("text"); + b.Property("ReportedRXDelay") + .HasColumnType("text"); - b.Property("SensorDecoder") - .HasColumnType("text"); + b.Property("SensorDecoder") + .HasColumnType("text"); - b.Property("Supports32BitFCnt") - .HasColumnType("boolean"); + b.Property("Supports32BitFCnt") + .HasColumnType("boolean"); - b.Property("TxPower") - .HasColumnType("text"); + b.Property("TxPower") + .HasColumnType("text"); - b.Property("UseOTAA") - .HasColumnType("boolean"); + b.Property("UseOTAA") + .HasColumnType("boolean"); - b.ToTable("LorawanDevices", (string)null); - }); + b.ToTable("LorawanDevices", (string)null); + }); modelBuilder.Entity("AzureIoTHub.Portal.Domain.Entities.Device", b => - { - b.HasOne("AzureIoTHub.Portal.Domain.Entities.DeviceModel", "DeviceModel") - .WithMany() - .HasForeignKey("DeviceModelId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); + { + b.HasOne("AzureIoTHub.Portal.Domain.Entities.DeviceModel", "DeviceModel") + .WithMany() + .HasForeignKey("DeviceModelId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); - b.Navigation("DeviceModel"); - }); + b.Navigation("DeviceModel"); + }); modelBuilder.Entity("AzureIoTHub.Portal.Domain.Entities.DeviceTagValue", b => - { - b.HasOne("AzureIoTHub.Portal.Domain.Entities.Device", null) - .WithMany("Tags") - .HasForeignKey("DeviceId"); + { + b.HasOne("AzureIoTHub.Portal.Domain.Entities.Device", null) + .WithMany("Tags") + .HasForeignKey("DeviceId"); - b.HasOne("AzureIoTHub.Portal.Domain.Entities.EdgeDevice", null) - .WithMany("Tags") - .HasForeignKey("EdgeDeviceId"); - }); + b.HasOne("AzureIoTHub.Portal.Domain.Entities.EdgeDevice", null) + .WithMany("Tags") + .HasForeignKey("EdgeDeviceId"); + }); modelBuilder.Entity("AzureIoTHub.Portal.Domain.Entities.EdgeDevice", b => - { - b.HasOne("AzureIoTHub.Portal.Domain.Entities.EdgeDeviceModel", "DeviceModel") - .WithMany() - .HasForeignKey("DeviceModelId") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); + { + b.HasOne("AzureIoTHub.Portal.Domain.Entities.EdgeDeviceModel", "DeviceModel") + .WithMany() + .HasForeignKey("DeviceModelId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); - b.Navigation("DeviceModel"); - }); + b.Navigation("DeviceModel"); + }); modelBuilder.Entity("AzureIoTHub.Portal.Domain.Entities.Label", b => - { - b.HasOne("AzureIoTHub.Portal.Domain.Entities.Device", null) - .WithMany("Labels") - .HasForeignKey("DeviceId"); + { + b.HasOne("AzureIoTHub.Portal.Domain.Entities.Device", null) + .WithMany("Labels") + .HasForeignKey("DeviceId"); - b.HasOne("AzureIoTHub.Portal.Domain.Entities.DeviceModel", null) - .WithMany("Labels") - .HasForeignKey("DeviceModelId"); + b.HasOne("AzureIoTHub.Portal.Domain.Entities.DeviceModel", null) + .WithMany("Labels") + .HasForeignKey("DeviceModelId"); - b.HasOne("AzureIoTHub.Portal.Domain.Entities.EdgeDevice", null) - .WithMany("Labels") - .HasForeignKey("EdgeDeviceId"); + b.HasOne("AzureIoTHub.Portal.Domain.Entities.EdgeDevice", null) + .WithMany("Labels") + .HasForeignKey("EdgeDeviceId"); - b.HasOne("AzureIoTHub.Portal.Domain.Entities.EdgeDeviceModel", null) - .WithMany("Labels") - .HasForeignKey("EdgeDeviceModelId"); - }); + b.HasOne("AzureIoTHub.Portal.Domain.Entities.EdgeDeviceModel", null) + .WithMany("Labels") + .HasForeignKey("EdgeDeviceModelId"); + }); modelBuilder.Entity("AzureIoTHub.Portal.Domain.Entities.LoRaDeviceTelemetry", b => - { - b.HasOne("AzureIoTHub.Portal.Domain.Entities.LorawanDevice", null) - .WithMany("Telemetry") - .HasForeignKey("LorawanDeviceId"); - }); + { + b.HasOne("AzureIoTHub.Portal.Domain.Entities.LorawanDevice", null) + .WithMany("Telemetry") + .HasForeignKey("LorawanDeviceId"); + }); modelBuilder.Entity("AzureIoTHub.Portal.Domain.Entities.LorawanDevice", b => - { - b.HasOne("AzureIoTHub.Portal.Domain.Entities.Device", null) - .WithOne() - .HasForeignKey("AzureIoTHub.Portal.Domain.Entities.LorawanDevice", "Id") - .OnDelete(DeleteBehavior.Cascade) - .IsRequired(); - }); + { + b.HasOne("AzureIoTHub.Portal.Domain.Entities.Device", null) + .WithOne() + .HasForeignKey("AzureIoTHub.Portal.Domain.Entities.LorawanDevice", "Id") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); modelBuilder.Entity("AzureIoTHub.Portal.Domain.Entities.Device", b => - { - b.Navigation("Labels"); + { + b.Navigation("Labels"); - b.Navigation("Tags"); - }); + b.Navigation("Tags"); + }); modelBuilder.Entity("AzureIoTHub.Portal.Domain.Entities.DeviceModel", b => - { - b.Navigation("Labels"); - }); + { + b.Navigation("Labels"); + }); modelBuilder.Entity("AzureIoTHub.Portal.Domain.Entities.EdgeDevice", b => - { - b.Navigation("Labels"); + { + b.Navigation("Labels"); - b.Navigation("Tags"); - }); + b.Navigation("Tags"); + }); modelBuilder.Entity("AzureIoTHub.Portal.Domain.Entities.EdgeDeviceModel", b => - { - b.Navigation("Labels"); - }); + { + b.Navigation("Labels"); + }); modelBuilder.Entity("AzureIoTHub.Portal.Domain.Entities.LorawanDevice", b => - { - b.Navigation("Telemetry"); - }); + { + b.Navigation("Telemetry"); + }); #pragma warning restore 612, 618 } } diff --git a/src/AzureIoTHub.Portal.Shared/Models/v1.0/IoTEdgeModelListItem.cs b/src/AzureIoTHub.Portal.Shared/Models/v1.0/IoTEdgeModelListItem.cs index 5f88b2d47..5c975bd3e 100644 --- a/src/AzureIoTHub.Portal.Shared/Models/v1.0/IoTEdgeModelListItem.cs +++ b/src/AzureIoTHub.Portal.Shared/Models/v1.0/IoTEdgeModelListItem.cs @@ -28,6 +28,12 @@ public class IoTEdgeModelListItem public Uri ImageUrl { get; set; } = default!; + /// + /// The aws deployment ID. + /// + public string IdProvider { get; set; } = default!; + + /// /// Gets the edge model labels. /// From 74676fb53f0ed605494ea519e5d3ce3c3eb8ec9e Mon Sep 17 00:00:00 2001 From: ssgueye2 Date: Thu, 25 May 2023 14:13:50 +0200 Subject: [PATCH 3/5] FIX Existing Failed Tests --- .../Services/AWS/AwsConfigService.cs | 1 - .../20230525074805_Add Aws DeploymentId.cs | 10 ++++---- .../Services/AWS_Tests/AwsConfigTests.cs | 24 +++++++++++++++++++ 3 files changed, 30 insertions(+), 5 deletions(-) diff --git a/src/AzureIoTHub.Portal.Infrastructure/Services/AWS/AwsConfigService.cs b/src/AzureIoTHub.Portal.Infrastructure/Services/AWS/AwsConfigService.cs index e4374d888..83bf44f62 100644 --- a/src/AzureIoTHub.Portal.Infrastructure/Services/AWS/AwsConfigService.cs +++ b/src/AzureIoTHub.Portal.Infrastructure/Services/AWS/AwsConfigService.cs @@ -12,7 +12,6 @@ namespace AzureIoTHub.Portal.Infrastructure.Services.AWS using Amazon.IoT; using Amazon.IoT.Model; using AutoMapper; - using AzureIoTHub.Portal.Application.Managers; using AzureIoTHub.Portal.Application.Services; using AzureIoTHub.Portal.Domain; using AzureIoTHub.Portal.Domain.Exceptions; diff --git a/src/AzureIoTHub.Portal.Postgres/Migrations/20230525074805_Add Aws DeploymentId.cs b/src/AzureIoTHub.Portal.Postgres/Migrations/20230525074805_Add Aws DeploymentId.cs index 5cf0008c8..c7b3d7174 100644 --- a/src/AzureIoTHub.Portal.Postgres/Migrations/20230525074805_Add Aws DeploymentId.cs +++ b/src/AzureIoTHub.Portal.Postgres/Migrations/20230525074805_Add Aws DeploymentId.cs @@ -1,16 +1,18 @@ -using Microsoft.EntityFrameworkCore.Migrations; - +// Copyright (c) CGI France. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. #nullable disable namespace AzureIoTHub.Portal.Postgres.Migrations { + using Microsoft.EntityFrameworkCore.Migrations; + /// public partial class AddAwsDeploymentId : Migration { /// protected override void Up(MigrationBuilder migrationBuilder) { - migrationBuilder.AddColumn( + _ = migrationBuilder.AddColumn( name: "IdProvider", table: "EdgeDeviceModels", type: "text", @@ -20,7 +22,7 @@ protected override void Up(MigrationBuilder migrationBuilder) /// protected override void Down(MigrationBuilder migrationBuilder) { - migrationBuilder.DropColumn( + _ = migrationBuilder.DropColumn( name: "IdProvider", table: "EdgeDeviceModels"); } diff --git a/src/AzureIoTHub.Portal.Tests.Unit/Infrastructure/Services/AWS_Tests/AwsConfigTests.cs b/src/AzureIoTHub.Portal.Tests.Unit/Infrastructure/Services/AWS_Tests/AwsConfigTests.cs index 2c7fed7b6..e63c1da70 100644 --- a/src/AzureIoTHub.Portal.Tests.Unit/Infrastructure/Services/AWS_Tests/AwsConfigTests.cs +++ b/src/AzureIoTHub.Portal.Tests.Unit/Infrastructure/Services/AWS_Tests/AwsConfigTests.cs @@ -22,6 +22,7 @@ namespace AzureIoTHub.Portal.Tests.Unit.Infrastructure.Services.AWS_Tests using System.Threading.Tasks; using Amazon.IoT; using Amazon.IoT.Model; + using AzureIoTHub.Portal.Domain.Entities; [TestFixture] public class AwsConfigTests : BackendUnitTest @@ -31,6 +32,8 @@ public class AwsConfigTests : BackendUnitTest private Mock mocDeviceModelImageManager; private Mock mockEdgeModelRepository; private Mock mockUnitOfWork; + private Mock mockConfigHandler; + private IConfigService awsConfigService; @@ -43,6 +46,8 @@ public void SetUp() this.mockGreengrasClient = MockRepository.Create(); this.mockIotClient = MockRepository.Create(); this.mocDeviceModelImageManager = MockRepository.Create(); + this.mockConfigHandler = MockRepository.Create(); + _ = ServiceCollection.AddSingleton(this.mockEdgeModelRepository.Object); _ = ServiceCollection.AddSingleton(this.mockGreengrasClient.Object); @@ -50,6 +55,8 @@ public void SetUp() _ = ServiceCollection.AddSingleton(this.mockUnitOfWork.Object); _ = ServiceCollection.AddSingleton(this.mocDeviceModelImageManager.Object); _ = ServiceCollection.AddSingleton(); + _ = ServiceCollection.AddSingleton(this.mockConfigHandler.Object); + Services = ServiceCollection.BuildServiceProvider(); @@ -61,7 +68,9 @@ public void SetUp() public async Task CreateDeploymentWithComponentsAndExistingThingGroupAndThingTypeShouldCreateTheDeployment() { //Act + var edge = Fixture.Create(); + var edgeDeviceModelEntity = Mapper.Map(edge); _ = this.mockIotClient.Setup(s3 => s3.DescribeThingGroupAsync(It.IsAny(), It.IsAny())) .ReturnsAsync(new DescribeThingGroupResponse @@ -83,6 +92,13 @@ public async Task CreateDeploymentWithComponentsAndExistingThingGroupAndThingTyp HttpStatusCode = HttpStatusCode.Created }); + _ = this.mockEdgeModelRepository.Setup(x => x.GetByIdAsync(It.IsAny())) + .ReturnsAsync(edgeDeviceModelEntity); + + _ = this.mockEdgeModelRepository.Setup(repository => repository.Update(It.IsAny())); + _ = this.mockUnitOfWork.Setup(work => work.SaveAsync()) + .Returns(Task.CompletedTask); + //Arrange await this.awsConfigService.RollOutEdgeModelConfiguration(edge); @@ -96,6 +112,7 @@ public async Task CreateDeploymentWithComponentsAndNonExistingThingGroupAndThing { //Act var edge = Fixture.Create(); + var edgeDeviceModelEntity = Mapper.Map(edge); _ = this.mockIotClient.Setup(s3 => s3.DescribeThingGroupAsync(It.IsAny(), It.IsAny())) .ThrowsAsync(new Amazon.IoT.Model.ResourceNotFoundException("Resource Not found")); @@ -120,6 +137,13 @@ public async Task CreateDeploymentWithComponentsAndNonExistingThingGroupAndThing HttpStatusCode = HttpStatusCode.Created }); + _ = this.mockEdgeModelRepository.Setup(x => x.GetByIdAsync(It.IsAny())) + .ReturnsAsync(edgeDeviceModelEntity); + + _ = this.mockEdgeModelRepository.Setup(repository => repository.Update(It.IsAny())); + _ = this.mockUnitOfWork.Setup(work => work.SaveAsync()) + .Returns(Task.CompletedTask); + //Arrange await this.awsConfigService.RollOutEdgeModelConfiguration(edge); From ea56b3e0befc2b4135b62dea854bc3e6994b70bb Mon Sep 17 00:00:00 2001 From: ssgueye2 Date: Thu, 25 May 2023 17:48:09 +0200 Subject: [PATCH 4/5] Update method done (But not tested) --- .../EdgeModels/EdgeModule/ModuleDialog.razor | 15 +++++- .../Services/AWS/AwsConfigService.cs | 8 +-- .../Services/EdgeModelService.cs | 6 ++- .../Models/v1.0/IoTEdgeModule.cs | 2 + .../Services/AWS_Tests/AwsConfigTests.cs | 38 +++++++++++++ .../Server/Services/EdgeModelServiceTest.cs | 53 +++++++++++++++++++ 6 files changed, 116 insertions(+), 6 deletions(-) diff --git a/src/AzureIoTHub.Portal.Client/Pages/EdgeModels/EdgeModule/ModuleDialog.razor b/src/AzureIoTHub.Portal.Client/Pages/EdgeModels/EdgeModule/ModuleDialog.razor index d807c792f..e171ad4b1 100644 --- a/src/AzureIoTHub.Portal.Client/Pages/EdgeModels/EdgeModule/ModuleDialog.razor +++ b/src/AzureIoTHub.Portal.Client/Pages/EdgeModels/EdgeModule/ModuleDialog.razor @@ -39,7 +39,17 @@ How to configure container create options for IoT Edge modules } - + else + { + + + + } + @@ -77,6 +87,7 @@ private string currentModuleName = default!; private string currentImageUri = default!; private string currentContainerCreateOptions = default!; + private string currentNumVersion = default!; private List currentEnvironmentVariables = new(); private List currentModuleIdentityTwinSettings = new(); @@ -92,6 +103,7 @@ currentModuleName = Module.ModuleName; currentImageUri = Module.ImageURI; currentContainerCreateOptions = Module.ContainerCreateOptions; + currentNumVersion = "1.0.0"; currentEnvironmentVariables = new List(Module.EnvironmentVariables.ToArray()); currentModuleIdentityTwinSettings = new List(Module.ModuleIdentityTwinSettings.ToArray()); currentCommands = new List(Module.Commands.ToArray()); @@ -104,6 +116,7 @@ Module.ModuleName = currentModuleName; Module.ImageURI = currentImageUri; Module.ContainerCreateOptions = currentContainerCreateOptions; + Module.Version = currentNumVersion; Module.EnvironmentVariables = new List(currentEnvironmentVariables.ToArray()); Module.ModuleIdentityTwinSettings = new List(currentModuleIdentityTwinSettings.ToArray()); Module.Commands = new List(currentCommands.ToArray()); diff --git a/src/AzureIoTHub.Portal.Infrastructure/Services/AWS/AwsConfigService.cs b/src/AzureIoTHub.Portal.Infrastructure/Services/AWS/AwsConfigService.cs index 83bf44f62..dbefca0fc 100644 --- a/src/AzureIoTHub.Portal.Infrastructure/Services/AWS/AwsConfigService.cs +++ b/src/AzureIoTHub.Portal.Infrastructure/Services/AWS/AwsConfigService.cs @@ -154,13 +154,12 @@ private async Task> CreateG InlineRecipe = recipeStream }; var response = await greengras.CreateComponentVersionAsync(componentVersion); - if (response.HttpStatusCode != HttpStatusCode.Created) { throw new InternalServerErrorException("The component creation failed due to an error in the Amazon IoT API."); } - listcomponentName.Add(component.ModuleName, new ComponentDeploymentSpecification { ComponentVersion = "1.0.0" }); + listcomponentName.Add(component.ModuleName, new ComponentDeploymentSpecification { ComponentVersion = component.Version }); } return listcomponentName; @@ -178,7 +177,7 @@ private static JObject JsonCreateComponent(IoTEdgeModule component) var recipeJson =new JObject( new JProperty("RecipeFormatVersion", "2020-01-25"), new JProperty("ComponentName", component.ModuleName), - new JProperty("ComponentVersion", "1.0.0"), + new JProperty("ComponentVersion", component.Version), new JProperty("ComponentPublisher", "IotHub"), new JProperty("ComponentDependencies", new JObject( @@ -285,7 +284,8 @@ public async Task> GetConfigModuleList(string modelId) { ModuleName = compoenent.Key, ImageURI = uriImage, - EnvironmentVariables = env + EnvironmentVariables = env, + Version = compoenent.Value.ComponentVersion }; moduleList.Add(iotEdgeModule); diff --git a/src/AzureIoTHub.Portal.Infrastructure/Services/EdgeModelService.cs b/src/AzureIoTHub.Portal.Infrastructure/Services/EdgeModelService.cs index e88fa790b..dbcec3694 100644 --- a/src/AzureIoTHub.Portal.Infrastructure/Services/EdgeModelService.cs +++ b/src/AzureIoTHub.Portal.Infrastructure/Services/EdgeModelService.cs @@ -260,7 +260,11 @@ public async Task UpdateEdgeModel(IoTEdgeModel edgeModel) await this.unitOfWork.SaveAsync(); - await SaveModuleCommands(edgeModel); + if (this.config.CloudProvider.Equals(CloudProviders.Azure, StringComparison.Ordinal)) + { + await SaveModuleCommands(edgeModel); + } + await this.configService.RollOutEdgeModelConfiguration(edgeModel); } diff --git a/src/AzureIoTHub.Portal.Shared/Models/v1.0/IoTEdgeModule.cs b/src/AzureIoTHub.Portal.Shared/Models/v1.0/IoTEdgeModule.cs index 41222c7fe..f6a60b00b 100644 --- a/src/AzureIoTHub.Portal.Shared/Models/v1.0/IoTEdgeModule.cs +++ b/src/AzureIoTHub.Portal.Shared/Models/v1.0/IoTEdgeModule.cs @@ -45,5 +45,7 @@ public class IoTEdgeModule /// The module commands. /// public List Commands { get; set; } = new List(); + + public string Version { get; set; } = default!; } } diff --git a/src/AzureIoTHub.Portal.Tests.Unit/Infrastructure/Services/AWS_Tests/AwsConfigTests.cs b/src/AzureIoTHub.Portal.Tests.Unit/Infrastructure/Services/AWS_Tests/AwsConfigTests.cs index e63c1da70..3d30916f7 100644 --- a/src/AzureIoTHub.Portal.Tests.Unit/Infrastructure/Services/AWS_Tests/AwsConfigTests.cs +++ b/src/AzureIoTHub.Portal.Tests.Unit/Infrastructure/Services/AWS_Tests/AwsConfigTests.cs @@ -23,6 +23,10 @@ namespace AzureIoTHub.Portal.Tests.Unit.Infrastructure.Services.AWS_Tests using Amazon.IoT; using Amazon.IoT.Model; using AzureIoTHub.Portal.Domain.Entities; + using System.Collections.Generic; + using System.IO; + using System.Text; + using Newtonsoft.Json.Linq; [TestFixture] public class AwsConfigTests : BackendUnitTest @@ -150,8 +154,42 @@ public async Task CreateDeploymentWithComponentsAndNonExistingThingGroupAndThing //Assert MockRepository.VerifyAll(); + } + [Test] + public async Task GetAllDeploymentComponentsShouldRetreiveImageUriAndEnvironmentVariables() + { + //Act + var edge = Fixture.Create(); + using var recipeAsMemoryStream = new MemoryStream(Encoding.UTF8.GetBytes(Fixture.Create().ToString())); + _ = this.mockConfigHandler.Setup(handler => handler.AWSRegion).Returns("eu-west-1"); + _ = this.mockConfigHandler.Setup(handler => handler.AWSAccountId).Returns("00000000"); + + _ = this.mockGreengrasClient.Setup(s3 => s3.GetDeploymentAsync(It.IsAny(), It.IsAny())) + .ReturnsAsync(new GetDeploymentResponse + { + HttpStatusCode = HttpStatusCode.OK, + Components = new Dictionary + { + {"test", new ComponentDeploymentSpecification()} + + } + }); + + _ = this.mockGreengrasClient.Setup(s3 => s3.GetComponentAsync(It.IsAny(), It.IsAny())) + .ReturnsAsync(new GetComponentResponse + { + HttpStatusCode = HttpStatusCode.OK, + Recipe = recipeAsMemoryStream, + RecipeOutputFormat = RecipeOutputFormat.JSON + }); + + //Arrange + _ = await this.awsConfigService.GetConfigModuleList(edge.IdProvider); + + //Assert + MockRepository.VerifyAll(); } } } diff --git a/src/AzureIoTHub.Portal.Tests.Unit/Server/Services/EdgeModelServiceTest.cs b/src/AzureIoTHub.Portal.Tests.Unit/Server/Services/EdgeModelServiceTest.cs index ccc884f8d..2ec275df1 100644 --- a/src/AzureIoTHub.Portal.Tests.Unit/Server/Services/EdgeModelServiceTest.cs +++ b/src/AzureIoTHub.Portal.Tests.Unit/Server/Services/EdgeModelServiceTest.cs @@ -171,6 +171,59 @@ public async Task GetEdgeModelShouldReturnValueAsync() _ = result.Should().BeEquivalentTo(expectedEdgeDeviceModel); } + [Test] + public async Task GetEdgeModelForAwsShouldReturnValueAsync() + { + // Arrange + _ = this.mockConfigHandler.Setup(handler => handler.CloudProvider).Returns("AWS"); + + var expectedModules = Fixture.CreateMany(2).ToList(); + + var expectedImageUri = Fixture.Create(); + + var expectedEdgeDeviceModel = new IoTEdgeModel() + { + ModelId = Guid.NewGuid().ToString(), + Name = Guid.NewGuid().ToString(), + ImageUrl = expectedImageUri, + Description = Guid.NewGuid().ToString(), + EdgeModules = expectedModules + }; + + var expectedCommands = Fixture.CreateMany(5).Select(command => + { + command.EdgeDeviceModelId = expectedEdgeDeviceModel.ModelId; + command.ModuleName = expectedModules[0].ModuleName; + return command; + }) .ToList(); + + expectedCommands.Add(new EdgeDeviceModelCommand + { + EdgeDeviceModelId = expectedEdgeDeviceModel.ModelId, + Id = Guid.NewGuid().ToString(), + Name = Guid.NewGuid().ToString(), + ModuleName = Guid.NewGuid().ToString() + }); + + var expectedEdgeDeviceModelEntity = Mapper.Map(expectedEdgeDeviceModel); + + _ = this.mockDeviceModelImageManager.Setup(c => c.ComputeImageUri(It.IsAny())) + .Returns(expectedImageUri); + + _ = this.mockEdgeDeviceModelRepository.Setup(x => x.GetByIdAsync(It.IsAny(), d => d.Labels)) + .ReturnsAsync(expectedEdgeDeviceModelEntity); + + _ = this.mockConfigService.Setup(x => x.GetConfigModuleList(It.IsAny())) + .ReturnsAsync(expectedModules); + + // Act + var result = await this.edgeDeviceModelService.GetEdgeModel(expectedEdgeDeviceModel.ModelId); + + // Assert + Assert.IsNotNull(result); + _ = result.Should().BeEquivalentTo(expectedEdgeDeviceModel); + } + [Test] public void GetEdgeModelShouldThrowResourceNotFoundExceptionIfModelDoesNotExist() { From 7cd6b86533a04a78a21c32391c1947131095d233 Mon Sep 17 00:00:00 2001 From: ssgueye2 Date: Thu, 25 May 2023 23:35:46 +0200 Subject: [PATCH 5/5] Fix Failed Tests + All tests for the update and the Get Deployment Done --- .../EdgeModels/EdgeModelDetailPage.razor | 181 +++++++++--------- .../EdgeModels/EdgeModule/ModuleDialog.razor | 10 +- .../Models/v1.0/IoTEdgeModule.cs | 1 + .../EdgeModels/EdgeModelDetailPageTest.cs | 22 ++- .../Server/Services/EdgeModelServiceTest.cs | 33 ++++ 5 files changed, 155 insertions(+), 92 deletions(-) diff --git a/src/AzureIoTHub.Portal.Client/Pages/EdgeModels/EdgeModelDetailPage.razor b/src/AzureIoTHub.Portal.Client/Pages/EdgeModels/EdgeModelDetailPage.razor index 1d199a89d..d5538a896 100644 --- a/src/AzureIoTHub.Portal.Client/Pages/EdgeModels/EdgeModelDetailPage.razor +++ b/src/AzureIoTHub.Portal.Client/Pages/EdgeModels/EdgeModelDetailPage.razor @@ -7,12 +7,15 @@ @using AzureIoTHub.Portal.Shared.Models.v10 @using AzureIoTHub.Portal.Client.Validators @using Microsoft.AspNetCore.Components.WebAssembly.Authentication +@using AzureIoTHub.Portal.Shared.Constants + @attribute [Authorize] @inject NavigationManager NavigationManager @inject IEdgeModelClientService EdgeModelService @inject ISnackbar Snackbar @inject IDialogService DialogService +@inject PortalSettings Portal @@ -69,44 +72,46 @@ - - - - - System Modules - - - - - - - - - - - Module name - Image URI - Detail - - - - - - - - - - - Detail - - - - - - - - - + @if (Portal.CloudProvider.Equals(CloudProviders.Azure)) + { + + + + System Modules + + + + + + + + + + + Module name + Image URI + Detail + + + + + + + + + + + Detail + + + + + + + + + } + @@ -149,55 +154,57 @@ - - - - - Routes - - - - - - - - - - - - Name - Value - Priority - Time To Live (Secs) - Delete - - - - - - - - - - - - - - - - - - - - Add new route - - - - - - - - + @if (Portal.CloudProvider.Equals(CloudProviders.Azure)) + { + + + + Routes + + + + + + + + + + + + Name + Value + Priority + Time To Live (Secs) + Delete + + + + + + + + + + + + + + + + + + + + Add new route + + + + + + + + } + diff --git a/src/AzureIoTHub.Portal.Client/Pages/EdgeModels/EdgeModule/ModuleDialog.razor b/src/AzureIoTHub.Portal.Client/Pages/EdgeModels/EdgeModule/ModuleDialog.razor index e171ad4b1..ecd1f1375 100644 --- a/src/AzureIoTHub.Portal.Client/Pages/EdgeModels/EdgeModule/ModuleDialog.razor +++ b/src/AzureIoTHub.Portal.Client/Pages/EdgeModels/EdgeModule/ModuleDialog.razor @@ -46,7 +46,11 @@ id=@nameof(IoTEdgeModule.Version) Label="Version Number" Variant="Variant.Outlined" - For="@(() => Module.Version)" /> + For="@(() => Module.Version)" + Required="true"/> + + + The Version should be incremented when updating the component } @@ -87,7 +91,7 @@ private string currentModuleName = default!; private string currentImageUri = default!; private string currentContainerCreateOptions = default!; - private string currentNumVersion = default!; + private string currentNumVersion = "1.0.0"; private List currentEnvironmentVariables = new(); private List currentModuleIdentityTwinSettings = new(); @@ -103,7 +107,7 @@ currentModuleName = Module.ModuleName; currentImageUri = Module.ImageURI; currentContainerCreateOptions = Module.ContainerCreateOptions; - currentNumVersion = "1.0.0"; + currentNumVersion = Module.Version; currentEnvironmentVariables = new List(Module.EnvironmentVariables.ToArray()); currentModuleIdentityTwinSettings = new List(Module.ModuleIdentityTwinSettings.ToArray()); currentCommands = new List(Module.Commands.ToArray()); diff --git a/src/AzureIoTHub.Portal.Shared/Models/v1.0/IoTEdgeModule.cs b/src/AzureIoTHub.Portal.Shared/Models/v1.0/IoTEdgeModule.cs index f6a60b00b..bcb3080ef 100644 --- a/src/AzureIoTHub.Portal.Shared/Models/v1.0/IoTEdgeModule.cs +++ b/src/AzureIoTHub.Portal.Shared/Models/v1.0/IoTEdgeModule.cs @@ -46,6 +46,7 @@ public class IoTEdgeModule /// public List Commands { get; set; } = new List(); + [Required(ErrorMessage = "The component version is required.")] public string Version { get; set; } = default!; } } diff --git a/src/AzureIoTHub.Portal.Tests.Unit/Client/Pages/EdgeModels/EdgeModelDetailPageTest.cs b/src/AzureIoTHub.Portal.Tests.Unit/Client/Pages/EdgeModels/EdgeModelDetailPageTest.cs index 5bbdc22c9..8ca91684a 100644 --- a/src/AzureIoTHub.Portal.Tests.Unit/Client/Pages/EdgeModels/EdgeModelDetailPageTest.cs +++ b/src/AzureIoTHub.Portal.Tests.Unit/Client/Pages/EdgeModels/EdgeModelDetailPageTest.cs @@ -44,6 +44,8 @@ public override void Setup() _ = Services.AddSingleton(this.mockEdgeModelService.Object); _ = Services.AddSingleton(this.mockDialogService.Object); _ = Services.AddSingleton(this.mockSnackbarService.Object); + _ = Services.AddSingleton(new PortalSettings { CloudProvider = "Azure" }); + this.mockNavigationManager = Services.GetRequiredService(); } @@ -52,6 +54,7 @@ public override void Setup() public void ClickOnReturnButtonMustNavigateToPreviousPage() { // Arrange + _ = SetupLoadEdgeModel(); var cut = RenderComponent(ComponentParameter.CreateParameter("ModelID", this.mockEdgeModleId)); @@ -68,6 +71,7 @@ public void ClickOnReturnButtonMustNavigateToPreviousPage() public void ClickOnSaveChangesShouldUpdateTheData() { // Arrange + var edgeModel = SetupLoadEdgeModel(); _ = this.mockEdgeModelService @@ -91,6 +95,7 @@ public void ClickOnSaveChangesShouldUpdateTheData() public void WhenModuleRequiredFieldEmptyClickOnSaveShouldProcessValidationError() { // Arrange + var edgeModel = SetupLoadEdgeModel(); _ = this.mockSnackbarService @@ -118,6 +123,7 @@ public void WhenModuleRequiredFieldEmptyClickOnSaveShouldProcessValidationError( public void WhenRoutesRequiredFieldEmptyClickOnSaveShouldProcessValidationError() { // Arrange + var edgeModel = SetupLoadEdgeModel(); _ = this.mockSnackbarService @@ -164,6 +170,7 @@ public void WhenClickOnSaveChangesShouldProssessProblem() public void ClickOnAddModuleShouldAddModuleOnEdgeModelData() { // Arrange + _ = SetupLoadEdgeModel(); // Act @@ -201,6 +208,7 @@ public void ClickOnDeleteModuleShouldRemoveModule() public void ClickOnDeleteEdgeModelButtonShouldShowDeleteDialogAndRedirectIfOk() { // Arrange + _ = SetupLoadEdgeModel(); var mockDialogReference = MockRepository.Create(); @@ -225,6 +233,7 @@ public void ClickOnDeleteEdgeModelButtonShouldShowDeleteDialogAndRedirectIfOk() public void ClickOnDeleteEdgeModelButtonShouldShowDeleteDialogAndReturnIfAborted() { // Arrange + _ = SetupLoadEdgeModel(); var mockDialogReference = MockRepository.Create(); @@ -248,6 +257,7 @@ public void ClickOnDeleteEdgeModelButtonShouldShowDeleteDialogAndReturnIfAborted public void ClickOnShowEditEdgeModuleDialogShouldShowDialog() { // Arrange + _ = SetupLoadEdgeModel(); var mockDialogReference = MockRepository.Create(); @@ -274,6 +284,7 @@ public void ClickOnShowEditEdgeModuleDialogShouldShowDialog() public void ClickShowEditEdgeModuleDialogShouldDisplayEditModuleDialogAndReturnIfAborted() { // Arrange + _ = SetupLoadEdgeModel(); var mockDialogReference = MockRepository.Create(); @@ -300,6 +311,7 @@ public void ClickShowEditEdgeModuleDialogShouldDisplayEditModuleDialogAndReturnI public void ClickOnShowSystemModuleDetailShouldShowDialog() { // Arrange + _ = SetupLoadEdgeModel(); var mockDialogReference = MockRepository.Create(); @@ -327,6 +339,7 @@ public void ClickOnShowSystemModuleDetailShouldShowDialog() public void ClickOnShowSystemModuleDetailShouldShowDialogAndReturnIfAborted() { // Arrange + _ = SetupLoadEdgeModel(); var mockDialogReference = MockRepository.Create(); @@ -354,6 +367,7 @@ public void ClickOnShowSystemModuleDetailShouldShowDialogAndReturnIfAborted() public void DeleteAvatarShouldRemoveTheImage() { // Arrange + _ = SetupLoadEdgeModel(); // Act @@ -384,10 +398,12 @@ public IoTEdgeModel SetupLoadEdgeModel() new IoTEdgeModule() { ModuleName = "module_Test", - ImageURI = "image_test" + ImageURI = "image_test", + Version = "1.0.1" } }, - ImageUrl = new Uri($"http://fake.local/{this.mockEdgeModleId}") + ImageUrl = new Uri($"http://fake.local/{this.mockEdgeModleId}"), + }; _ = this.mockEdgeModelService @@ -405,6 +421,7 @@ public IoTEdgeModel SetupLoadEdgeModel() public void ClickOnAddRouteShouldAddRouteOnEdgeModelData() { // Arrange + _ = SetupLoadEdgeModel(); // Act @@ -422,6 +439,7 @@ public void ClickOnAddRouteShouldAddRouteOnEdgeModelData() public void ClickOnDeleteRouteShouldRemoveRouteFromEdgeModelData() { // Arrange + _ = SetupLoadEdgeModel(); // Act diff --git a/src/AzureIoTHub.Portal.Tests.Unit/Server/Services/EdgeModelServiceTest.cs b/src/AzureIoTHub.Portal.Tests.Unit/Server/Services/EdgeModelServiceTest.cs index 2ec275df1..e2cd9c466 100644 --- a/src/AzureIoTHub.Portal.Tests.Unit/Server/Services/EdgeModelServiceTest.cs +++ b/src/AzureIoTHub.Portal.Tests.Unit/Server/Services/EdgeModelServiceTest.cs @@ -352,6 +352,8 @@ public void CreateEdgeModelShouldThrowInternalServerErrorExceptionIfDbUpdateExce public async Task UpdateEdgeModelShouldUpdateEdgeModel() { // Arrange + _ = this.mockConfigHandler.Setup(handler => handler.CloudProvider).Returns("Azure"); + var edgeDeviceModel = Fixture.Create(); var edgeDeviceModelEntity = Mapper.Map(edgeDeviceModel); @@ -386,6 +388,37 @@ public async Task UpdateEdgeModelShouldUpdateEdgeModel() MockRepository.VerifyAll(); } + + [Test] + public async Task UpdateEdgeModelForAWSShouldUpdateEdgeModel() + { + // Arrange + _ = this.mockConfigHandler.Setup(handler => handler.CloudProvider).Returns("AWS"); + + var edgeDeviceModel = Fixture.Create(); + var edgeDeviceModelEntity = Mapper.Map(edgeDeviceModel); + + _ = this.mockEdgeDeviceModelRepository.Setup(x => x.GetByIdAsync(It.IsAny(), d => d.Labels)) + .ReturnsAsync(edgeDeviceModelEntity); + + this.mockLabelRepository.Setup(repository => repository.Delete(It.IsAny())) + .Verifiable(); + + _ = this.mockEdgeDeviceModelRepository.Setup(repository => repository.Update(It.IsAny())); + _ = this.mockUnitOfWork.Setup(work => work.SaveAsync()) + .Returns(Task.CompletedTask); + + + _ = this.mockConfigService.Setup(x => x.RollOutEdgeModelConfiguration(It.IsAny())) + .Returns(Task.CompletedTask); + + // Act + await this.edgeDeviceModelService.UpdateEdgeModel(edgeDeviceModel); + + // Assert + MockRepository.VerifyAll(); + } + [Test] public void UpdateEdgeModelShouldThrowResourceNotFoundExceptionIfModelDoesNotExist() {