From 495b78463bf764bc1d152ee8b9ebd052cbc86bf5 Mon Sep 17 00:00:00 2001 From: ssgueye2 <127868584+ssgueye2@users.noreply.github.com> Date: Wed, 31 May 2023 09:45:02 +0200 Subject: [PATCH] Sync GreenGrassDeployment (#2120) * Sync GreenGrassDeployment (Started) * Sync Deployments (waiting for one test) * Sync Deployment (DONE) * remove getComponentIfExist * Sync GreenGrassDeployment (Started) * Sync Deployments (waiting for one test) * Sync Deployment (DONE) * remove getComponentIfExist * update Sync Deployment With Dynamic Thing group --- .../Jobs/AWS/SyncGreenGrassDeploymentsJob.cs | 152 ++++++++++++++++++ .../Jobs/AWS/SyncThingTypesJob.cs | 6 +- .../Services/AWS/AwsConfigService.cs | 38 +++-- .../Services/EdgeModelService.cs | 10 +- .../Startup/AWSServiceCollectionExtension.cs | 8 + .../AWS/SyncGreenGrassDeploymentsJobTests.cs | 138 ++++++++++++++++ .../Services/AWS_Tests/AwsConfigTests.cs | 60 ++++++- .../Server/Services/EdgeModelServiceTest.cs | 5 - 8 files changed, 392 insertions(+), 25 deletions(-) create mode 100644 src/AzureIoTHub.Portal.Infrastructure/Jobs/AWS/SyncGreenGrassDeploymentsJob.cs create mode 100644 src/AzureIoTHub.Portal.Tests.Unit/Infrastructure/Jobs/AWS/SyncGreenGrassDeploymentsJobTests.cs diff --git a/src/AzureIoTHub.Portal.Infrastructure/Jobs/AWS/SyncGreenGrassDeploymentsJob.cs b/src/AzureIoTHub.Portal.Infrastructure/Jobs/AWS/SyncGreenGrassDeploymentsJob.cs new file mode 100644 index 000000000..bb27e5bea --- /dev/null +++ b/src/AzureIoTHub.Portal.Infrastructure/Jobs/AWS/SyncGreenGrassDeploymentsJob.cs @@ -0,0 +1,152 @@ +// Copyright (c) CGI France. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +namespace AzureIoTHub.Portal.Infrastructure.Jobs.AWS +{ + using Amazon.IoT; + using AutoMapper; + using AzureIoTHub.Portal.Application.Managers; + using AzureIoTHub.Portal.Domain.Repositories; + using AzureIoTHub.Portal.Domain; + using Microsoft.Extensions.Logging; + using Quartz; + using Amazon.GreengrassV2; + using AzureIoTHub.Portal.Models.v10; + using Amazon.GreengrassV2.Model; + using AzureIoTHub.Portal.Domain.Entities; + using System.Text.RegularExpressions; + + [DisallowConcurrentExecution] + public class SyncGreenGrassDeploymentsJob : IJob + { + private readonly ILogger logger; + private readonly IMapper mapper; + private readonly IUnitOfWork unitOfWork; + private readonly IEdgeDeviceModelRepository edgeDeviceModelRepository; + private readonly IAmazonIoT amazonIoTClient; + private readonly IAmazonGreengrassV2 amazonGreenGrass; + private readonly IDeviceModelImageManager deviceModelImageManager; + + public SyncGreenGrassDeploymentsJob( + ILogger logger, + IMapper mapper, + IUnitOfWork unitOfWork, + IEdgeDeviceModelRepository edgeDeviceModelRepository, + IAmazonIoT amazonIoTClient, + IAmazonGreengrassV2 amazonGreenGrass, + IDeviceModelImageManager awsImageManager) + { + this.deviceModelImageManager = awsImageManager; + this.mapper = mapper; + this.unitOfWork = unitOfWork; + this.edgeDeviceModelRepository = edgeDeviceModelRepository; + this.amazonIoTClient = amazonIoTClient; + this.amazonGreenGrass = amazonGreenGrass; + this.logger = logger; + } + + + public async Task Execute(IJobExecutionContext context) + { + try + { + this.logger.LogInformation("Start of sync Greengrass Deployents job"); + + await SyncGreenGrassDeployments(); + + this.logger.LogInformation("End of sync Greengrass Deployents job"); + } + catch (Exception e) + { + this.logger.LogError(e, "Sync Greengrass Deployents job has failed"); + } + } + + private async Task SyncGreenGrassDeployments() + { + var awsGreenGrassDeployments = await GetAllGreenGrassDeployments(); + + foreach (var deployment in awsGreenGrassDeployments) + { + await CreateNonExisitingGreenGrassDeployment(deployment); + } + + //Delete in DB AWS deleted deployments + await DeleteGreenGrassDeployments(awsGreenGrassDeployments); + } + + private async Task> GetAllGreenGrassDeployments() + { + var deployments = new List(); + + var nextToken = string.Empty; + + var getAllAwsGreenGrassDeployments = await this.amazonGreenGrass.ListDeploymentsAsync( + new ListDeploymentsRequest + { + NextToken = nextToken, + HistoryFilter = DeploymentHistoryFilter.LATEST_ONLY + }); + + foreach (var deployment in getAllAwsGreenGrassDeployments.Deployments) + { + var awsThingGroupRegex = new Regex(@"/([^/]+)$"); + var matches = awsThingGroupRegex.Match(deployment.TargetArn); + + if (matches.Success && matches.Groups.Count > 1) + { + var thinggroupName = matches.Groups[1].Value; + var s = await this.amazonIoTClient.DescribeThingGroupAsync(new Amazon.IoT.Model.DescribeThingGroupRequest { ThingGroupName = thinggroupName }); + if (s.QueryString != null) + { + var iotEdgeModel = new IoTEdgeModel + { + ModelId = deployment.DeploymentId, //Instead of giving a random Id here, we can give the deploymentID + Name = deployment.DeploymentName, + ExternalIdentifier = deployment.DeploymentId + }; + deployments.Add(iotEdgeModel); + } + } + + } + return deployments; + } + + private async Task CreateNonExisitingGreenGrassDeployment(IoTEdgeModel iotEdgeModel) + { + + var iotEdgeModels = (await this.edgeDeviceModelRepository.GetAllAsync()) + .Where(edge => edge.ExternalIdentifier!.Equals(iotEdgeModel.ExternalIdentifier, StringComparison.Ordinal)).ToList(); + + if (iotEdgeModels.Count == 0) + { + //In Aws, it is possible to create a deployment without a name, so it will take the id as a name + //Here is how we handle it + iotEdgeModel.Name ??= iotEdgeModel.ModelId; + + var edgeModel = this.mapper.Map(iotEdgeModel); + + await this.edgeDeviceModelRepository.InsertAsync(edgeModel); + await this.unitOfWork.SaveAsync(); + _ = this.deviceModelImageManager.SetDefaultImageToModel(edgeModel.Id); + } + + } + + private async Task DeleteGreenGrassDeployments(List edgeModels) + { + //Get All Deployments that are not in AWS + var deploymentToDelete = (await this.edgeDeviceModelRepository.GetAllAsync()) + .Where(edge => !edgeModels.Any(edgeModel => edge.ExternalIdentifier!.Equals(edgeModel.ExternalIdentifier, StringComparison.Ordinal))) + .ToList(); + + foreach (var edgeModel in deploymentToDelete) + { + await this.deviceModelImageManager.DeleteDeviceModelImageAsync(edgeModel.Id); + this.edgeDeviceModelRepository.Delete(edgeModel.Id); + await this.unitOfWork.SaveAsync(); + } + } + } +} diff --git a/src/AzureIoTHub.Portal.Infrastructure/Jobs/AWS/SyncThingTypesJob.cs b/src/AzureIoTHub.Portal.Infrastructure/Jobs/AWS/SyncThingTypesJob.cs index 6f728761d..1533f80df 100644 --- a/src/AzureIoTHub.Portal.Infrastructure/Jobs/AWS/SyncThingTypesJob.cs +++ b/src/AzureIoTHub.Portal.Infrastructure/Jobs/AWS/SyncThingTypesJob.cs @@ -183,13 +183,13 @@ private async Task DeleteThingTypes(List thingTypes) thingTypes.Any(thingType => deviceModel.Id.Equals(thingType.ThingTypeId, StringComparison.Ordinal) && thingType.ThingTypeMetadata.Deprecated)) .ToList(); - deviceModelsToDelete.ForEach(async deviceModel => + foreach (var deviceModel in deviceModelsToDelete) { await this.deviceModelImageManager.DeleteDeviceModelImageAsync(deviceModel.Id); this.deviceModelRepository.Delete(deviceModel.Id); - }); + await this.unitOfWork.SaveAsync(); + } - await this.unitOfWork.SaveAsync(); } } diff --git a/src/AzureIoTHub.Portal.Infrastructure/Services/AWS/AwsConfigService.cs b/src/AzureIoTHub.Portal.Infrastructure/Services/AWS/AwsConfigService.cs index 8b3d9ef29..598200617 100644 --- a/src/AzureIoTHub.Portal.Infrastructure/Services/AWS/AwsConfigService.cs +++ b/src/AzureIoTHub.Portal.Infrastructure/Services/AWS/AwsConfigService.cs @@ -145,28 +145,42 @@ private async Task> CreateG var listcomponentName = new Dictionary(); foreach (var component in edgeModel.EdgeModules) { - var recipeJson = JsonCreateComponent(component); - var recipeBytes = Encoding.UTF8.GetBytes(recipeJson.ToString()); - var recipeStream = new MemoryStream(recipeBytes); - - var componentVersion = new CreateComponentVersionRequest + try { - InlineRecipe = recipeStream - }; - var response = await greengras.CreateComponentVersionAsync(componentVersion); - if (response.HttpStatusCode != HttpStatusCode.Created) + _ = await this.greengras.DescribeComponentAsync(new DescribeComponentRequest + { + Arn = $"arn:aws:greengrass:{config.AWSRegion}:{config.AWSAccountId}:components:{component.ModuleName}:versions:{component.Version}" + }); + listcomponentName.Add(component.ModuleName, new ComponentDeploymentSpecification { ComponentVersion = component.Version }); + + } + catch (Amazon.GreengrassV2.Model.ResourceNotFoundException) { - throw new InternalServerErrorException("The component creation failed due to an error in the Amazon IoT API."); + var recipeJson = JsonCreateComponent(component); + var recipeBytes = Encoding.UTF8.GetBytes(recipeJson.ToString()); + var recipeStream = new MemoryStream(recipeBytes); + var componentVersion = new CreateComponentVersionRequest + { + 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 = component.Version }); } - listcomponentName.Add(component.ModuleName, new ComponentDeploymentSpecification { ComponentVersion = component.Version }); } + return listcomponentName; } private static JObject JsonCreateComponent(IoTEdgeModule component) { + var environmentVariableObject = new JObject(); foreach (var env in component.EnvironmentVariables) @@ -329,7 +343,7 @@ public async Task> GetConfigModuleList(string modelId) } return moduleList; } - catch (Amazon.IoT.Model.ResourceNotFoundException) + catch (Amazon.GreengrassV2.Model.ResourceNotFoundException) { throw new InternalServerErrorException("The deployment is not found"); diff --git a/src/AzureIoTHub.Portal.Infrastructure/Services/EdgeModelService.cs b/src/AzureIoTHub.Portal.Infrastructure/Services/EdgeModelService.cs index 96087e3a9..ea68eda6a 100644 --- a/src/AzureIoTHub.Portal.Infrastructure/Services/EdgeModelService.cs +++ b/src/AzureIoTHub.Portal.Infrastructure/Services/EdgeModelService.cs @@ -255,13 +255,15 @@ public async Task UpdateEdgeModel(IoTEdgeModel edgeModel) this.labelRepository.Delete(labelEntity.Id); } - _ = this.mapper.Map(edgeModel, edgeModelEntity); - this.edgeModelRepository.Update(edgeModelEntity); - - await this.unitOfWork.SaveAsync(); + // For AWS, we do the update in the AwsConfiguration if (this.config.CloudProvider.Equals(CloudProviders.Azure, StringComparison.Ordinal)) { + _ = this.mapper.Map(edgeModel, edgeModelEntity); + + this.edgeModelRepository.Update(edgeModelEntity); + await this.unitOfWork.SaveAsync(); + await SaveModuleCommands(edgeModel); } diff --git a/src/AzureIoTHub.Portal.Infrastructure/Startup/AWSServiceCollectionExtension.cs b/src/AzureIoTHub.Portal.Infrastructure/Startup/AWSServiceCollectionExtension.cs index b2e501114..0095297fd 100644 --- a/src/AzureIoTHub.Portal.Infrastructure/Startup/AWSServiceCollectionExtension.cs +++ b/src/AzureIoTHub.Portal.Infrastructure/Startup/AWSServiceCollectionExtension.cs @@ -84,6 +84,14 @@ private static IServiceCollection ConfigureAWSSyncJobs(this IServiceCollection s .WithSimpleSchedule(s => s .WithIntervalInMinutes(configuration.SyncDatabaseJobRefreshIntervalInMinutes) .RepeatForever())); + + _ = q.AddJob(j => j.WithIdentity(nameof(SyncGreenGrassDeploymentsJob))) + .AddTrigger(t => t + .WithIdentity($"{nameof(SyncGreenGrassDeploymentsJob)}") + .ForJob(nameof(SyncGreenGrassDeploymentsJob)) + .WithSimpleSchedule(s => s + .WithIntervalInMinutes(configuration.SyncDatabaseJobRefreshIntervalInMinutes) + .RepeatForever())); }); } diff --git a/src/AzureIoTHub.Portal.Tests.Unit/Infrastructure/Jobs/AWS/SyncGreenGrassDeploymentsJobTests.cs b/src/AzureIoTHub.Portal.Tests.Unit/Infrastructure/Jobs/AWS/SyncGreenGrassDeploymentsJobTests.cs new file mode 100644 index 000000000..14018e142 --- /dev/null +++ b/src/AzureIoTHub.Portal.Tests.Unit/Infrastructure/Jobs/AWS/SyncGreenGrassDeploymentsJobTests.cs @@ -0,0 +1,138 @@ +// Copyright (c) CGI France. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +namespace AzureIoTHub.Portal.Tests.Unit.Infrastructure.Jobs.AWS +{ + using System; + using System.Collections.Generic; + using System.Threading; + using System.Threading.Tasks; + using Amazon.GreengrassV2; + using Amazon.GreengrassV2.Model; + using Amazon.IoT; + using Amazon.IoT.Model; + using AutoFixture; + using AzureIoTHub.Portal.Application.Managers; + using AzureIoTHub.Portal.Domain; + using AzureIoTHub.Portal.Domain.Entities; + using AzureIoTHub.Portal.Domain.Repositories; + using AzureIoTHub.Portal.Infrastructure.Jobs.AWS; + using AzureIoTHub.Portal.Tests.Unit.UnitTests.Bases; + using Microsoft.Extensions.DependencyInjection; + using Moq; + using NUnit.Framework; + using Quartz; + + public class SyncGreenGrassDeploymentsJobTests : BackendUnitTest + { + private IJob syncGreenGrassJob; + + private Mock mockUnitOfWork; + private Mock mockEdgeDeviceModelRepository; + private Mock mockAmazonIoTClient; + private Mock mockAmazonGreenGrass; + private Mock mockDeviceModelImageManager; + + public override void Setup() + { + base.Setup(); + + this.mockDeviceModelImageManager = MockRepository.Create(); + this.mockUnitOfWork = MockRepository.Create(); + this.mockEdgeDeviceModelRepository = MockRepository.Create(); + this.mockAmazonIoTClient = MockRepository.Create(); + this.mockAmazonGreenGrass = MockRepository.Create(); + + _ = ServiceCollection.AddSingleton(this.mockDeviceModelImageManager.Object); + _ = ServiceCollection.AddSingleton(this.mockUnitOfWork.Object); + _ = ServiceCollection.AddSingleton(this.mockEdgeDeviceModelRepository.Object); + _ = ServiceCollection.AddSingleton(this.mockAmazonIoTClient.Object); + _ = ServiceCollection.AddSingleton(this.mockAmazonGreenGrass.Object); + _ = ServiceCollection.AddSingleton(); + + + Services = ServiceCollection.BuildServiceProvider(); + + this.syncGreenGrassJob = Services.GetRequiredService(); + } + + [Test] + public async Task ExecuteSyncExistingAWSDeploymentsAndCreateNinExistingDeploymentInDB() + { + + //Arrange + var mockJobExecutionContext = MockRepository.Create(); + + var deploymentId = Fixture.Create(); + var nonExistingDeploymentId = Fixture.Create(); + + var listDeploymentsInAws = new ListDeploymentsResponse + { + Deployments = new List() + { + new Deployment + { + DeploymentId = deploymentId, + TargetArn = "arn:aws:iot:eu-west-1:0000000000:thinggroup/DemoEdgeModel" + }, + new Deployment + { + DeploymentId = Fixture.Create(), + TargetArn = "arn:aws:iot:eu-west-1:0000000000:thinggroup/toto" + + }, + new Deployment + { + DeploymentId = Fixture.Create(), + TargetArn = "arn:aws:iot:eu-west-1:0000000000:thinggroup/titi" + + } + } + }; + var existingDeployments = new List + { + new EdgeDeviceModel + { + Id = Fixture.Create(), + ExternalIdentifier = deploymentId, + }, + new EdgeDeviceModel + { + Id = nonExistingDeploymentId, + ExternalIdentifier = nonExistingDeploymentId, + } + }; + + _ = this.mockAmazonGreenGrass.Setup(greengrass => greengrass.ListDeploymentsAsync(It.IsAny(), It.IsAny())) + .ReturnsAsync(listDeploymentsInAws); + + _ = this.mockAmazonIoTClient.Setup(iot => iot.DescribeThingGroupAsync(It.IsAny(), It.IsAny())) + .ReturnsAsync(Fixture.Create); + + _ = this.mockEdgeDeviceModelRepository.Setup(u => u.GetAllAsync(null, It.IsAny())) + .ReturnsAsync(existingDeployments); + + _ = this.mockEdgeDeviceModelRepository.Setup(u => u.InsertAsync(It.Is(s => !s.ExternalIdentifier.Equals(deploymentId, StringComparison.Ordinal)))) + .Returns(Task.CompletedTask); + _ = this.mockDeviceModelImageManager.Setup(c => c.SetDefaultImageToModel(It.Is(s => !s.Equals(deploymentId, StringComparison.Ordinal)))) + .ReturnsAsync(Fixture.Create()); + + this.mockEdgeDeviceModelRepository.Setup(u => u.Delete(It.Is(s => s.Equals(nonExistingDeploymentId, StringComparison.Ordinal)))) + .Verifiable(); + + _ = this.mockDeviceModelImageManager.Setup(c => c.DeleteDeviceModelImageAsync(It.Is(s => s.Equals(nonExistingDeploymentId, StringComparison.Ordinal)))) + .Returns(Task.CompletedTask); + + _ = this.mockUnitOfWork.Setup(c => c.SaveAsync()) + .Returns(Task.CompletedTask); + + // Act + await this.syncGreenGrassJob.Execute(mockJobExecutionContext.Object); + + // Assert + MockRepository.VerifyAll(); + + } + + } +} 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 ce13873fa..2fa4c0b8a 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 @@ -72,6 +72,8 @@ public void SetUp() public async Task CreateDeploymentWithComponentsAndExistingThingGroupAndThingTypeShouldCreateTheDeployment() { //Act + _ = this.mockConfigHandler.Setup(handler => handler.AWSRegion).Returns("eu-west-1"); + _ = this.mockConfigHandler.Setup(handler => handler.AWSAccountId).Returns("00000000"); var edge = Fixture.Create(); var edgeDeviceModelEntity = Mapper.Map(edge); @@ -90,6 +92,10 @@ public async Task CreateDeploymentWithComponentsAndExistingThingGroupAndThingTyp { HttpStatusCode = HttpStatusCode.Created }); + + _ = this.mockGreengrasClient.Setup(s3 => s3.DescribeComponentAsync(It.IsAny(), It.IsAny())) + + .ThrowsAsync(new Amazon.GreengrassV2.Model.ResourceNotFoundException("Resource Not found")); _ = this.mockGreengrasClient.Setup(s3 => s3.CreateComponentVersionAsync(It.IsAny(), It.IsAny())) .ReturnsAsync(new CreateComponentVersionResponse { @@ -112,9 +118,58 @@ public async Task CreateDeploymentWithComponentsAndExistingThingGroupAndThingTyp } [Test] - public async Task CreateDeploymentWithComponentsAndNonExistingThingGroupAndThingTypeShouldCreateThingGroupAndThingTypeAndTheDeployment() + public async Task CreateDeploymentWithExistingComponentsAndExistingThingGroupAndThingTypeShouldCreateTheDeployment() { //Act + _ = this.mockConfigHandler.Setup(handler => handler.AWSRegion).Returns("eu-west-1"); + _ = this.mockConfigHandler.Setup(handler => handler.AWSAccountId).Returns("00000000"); + + var edge = Fixture.Create(); + var edgeDeviceModelEntity = Mapper.Map(edge); + + _ = this.mockIotClient.Setup(s3 => s3.DescribeThingGroupAsync(It.IsAny(), It.IsAny())) + .ReturnsAsync(new DescribeThingGroupResponse + { + HttpStatusCode = HttpStatusCode.OK + }); + + _ = this.mockIotClient.Setup(s3 => s3.DescribeThingTypeAsync(It.IsAny(), It.IsAny())) + .ReturnsAsync(new DescribeThingTypeResponse()); + + _ = this.mockGreengrasClient.Setup(s3 => s3.CreateDeploymentAsync(It.IsAny(), It.IsAny())) + .ReturnsAsync(new CreateDeploymentResponse + { + HttpStatusCode = HttpStatusCode.Created + }); + + _ = this.mockGreengrasClient.Setup(s3 => s3.DescribeComponentAsync(It.IsAny(), It.IsAny())) + .ReturnsAsync(new DescribeComponentResponse + { + HttpStatusCode = HttpStatusCode.OK + }); + + _ = 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); + + //Assert + MockRepository.VerifyAll(); + + } + + [Test] + public async Task CreateDeploymentWithNonExistingComponentsAndNonExistingThingGroupAndThingTypeShouldCreateThingGroupAndThingTypeAndTheDeployment() + { + //Act + _ = this.mockConfigHandler.Setup(handler => handler.AWSRegion).Returns("eu-west-1"); + _ = this.mockConfigHandler.Setup(handler => handler.AWSAccountId).Returns("00000000"); + var edge = Fixture.Create(); var edgeDeviceModelEntity = Mapper.Map(edge); @@ -135,6 +190,9 @@ public async Task CreateDeploymentWithComponentsAndNonExistingThingGroupAndThing { HttpStatusCode = HttpStatusCode.Created }); + _ = this.mockGreengrasClient.Setup(s3 => s3.DescribeComponentAsync(It.IsAny(), It.IsAny())) + .ThrowsAsync(new Amazon.GreengrassV2.Model.ResourceNotFoundException("Resource Not found")); + _ = this.mockGreengrasClient.Setup(s3 => s3.CreateComponentVersionAsync(It.IsAny(), It.IsAny())) .ReturnsAsync(new CreateComponentVersionResponse { diff --git a/src/AzureIoTHub.Portal.Tests.Unit/Server/Services/EdgeModelServiceTest.cs b/src/AzureIoTHub.Portal.Tests.Unit/Server/Services/EdgeModelServiceTest.cs index 6857ad796..a02deb186 100644 --- a/src/AzureIoTHub.Portal.Tests.Unit/Server/Services/EdgeModelServiceTest.cs +++ b/src/AzureIoTHub.Portal.Tests.Unit/Server/Services/EdgeModelServiceTest.cs @@ -404,11 +404,6 @@ public async Task UpdateEdgeModelForAWSShouldUpdateEdgeModel() 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);