From 417ed32b3dc88f4255ed1f5aeed0c05c4a65143d Mon Sep 17 00:00:00 2001 From: crib Date: Tue, 20 Dec 2022 09:03:37 +0100 Subject: [PATCH 1/6] The default image of a new device model or edge model should be the default image --- .../AzureIoTHub.Portal.Infrastructure.csproj | 1 + .../Managers/DeviceModelImageManager.cs | 20 +++++++++++++ .../Services/EdgeModelService.cs | 28 +++++++++++++++++++ 3 files changed, 49 insertions(+) diff --git a/src/AzureIoTHub.Portal.Infrastructure/AzureIoTHub.Portal.Infrastructure.csproj b/src/AzureIoTHub.Portal.Infrastructure/AzureIoTHub.Portal.Infrastructure.csproj index 562324a4a..ba1c7d5d4 100644 --- a/src/AzureIoTHub.Portal.Infrastructure/AzureIoTHub.Portal.Infrastructure.csproj +++ b/src/AzureIoTHub.Portal.Infrastructure/AzureIoTHub.Portal.Infrastructure.csproj @@ -131,6 +131,7 @@ + diff --git a/src/AzureIoTHub.Portal.Infrastructure/Managers/DeviceModelImageManager.cs b/src/AzureIoTHub.Portal.Infrastructure/Managers/DeviceModelImageManager.cs index 7c29b751b..a408f2053 100644 --- a/src/AzureIoTHub.Portal.Infrastructure/Managers/DeviceModelImageManager.cs +++ b/src/AzureIoTHub.Portal.Infrastructure/Managers/DeviceModelImageManager.cs @@ -53,6 +53,26 @@ public async Task ChangeDeviceModelImageAsync(string deviceModelId, Stre return blobClient.Uri.ToString(); } + public async Task SetDefaultImageToModel(string deviceModelId) + { + var blobContainer = this.blobService.GetBlobContainerClient(this.deviceModelImageOptions.Value.ImageContainerName); + + var blobClient = blobContainer.GetBlobClient(deviceModelId); + + this.logger.LogInformation($"Uploading to Blob storage as blob:\n\t {blobClient.Uri}\n"); + + var currentAssembly = Assembly.GetExecutingAssembly(); + + using var defaultImageStream = currentAssembly + .GetManifestResourceStream($"{currentAssembly.GetName().Name}.Resources.{this.deviceModelImageOptions.Value.DefaultImageName}"); + + _ = await blobClient.UploadAsync(defaultImageStream, true); + + _ = await blobClient.SetHttpHeadersAsync(new BlobHttpHeaders { CacheControl = $"max-age={this.configHandler.StorageAccountDeviceModelImageMaxAge}, must-revalidate" }); + + return blobClient.Uri.ToString(); + } + public async Task DeleteDeviceModelImageAsync(string deviceModelId) { var blobContainer = this.blobService.GetBlobContainerClient(this.deviceModelImageOptions.Value.ImageContainerName); diff --git a/src/AzureIoTHub.Portal.Server/Services/EdgeModelService.cs b/src/AzureIoTHub.Portal.Server/Services/EdgeModelService.cs index 70d536b1b..a6486113f 100644 --- a/src/AzureIoTHub.Portal.Server/Services/EdgeModelService.cs +++ b/src/AzureIoTHub.Portal.Server/Services/EdgeModelService.cs @@ -103,6 +103,34 @@ public async Task CreateEdgeModel(IoTEdgeModel edgeModel) await this.configService.RollOutEdgeModelConfiguration(edgeModel); } + /// + /// Create a new edge model template and roll out + /// the edge model configuration. + /// + /// the new edge modle object. + /// nothing. + /// If edge model template already exist return ResourceAlreadyExistsException. + /// + public async Task CreateDefaultImageToEdgeModel(IoTEdgeModel edgeModel) + { + 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"); + } + + this.deviceModelImageManager.SetDefaultImageToModel(edgeModel.ModelId); + + await SaveModuleCommands(edgeModel); + await this.configService.RollOutEdgeModelConfiguration(edgeModel); + } + /// /// Saves the module commands for a specific model object. /// From ece1363c57b0882a769b05e94242c7a97f70113b Mon Sep 17 00:00:00 2001 From: crib Date: Tue, 20 Dec 2022 09:48:54 +0100 Subject: [PATCH 2/6] Code ok --- .../Managers/IDeviceModelImageManager.cs | 2 ++ src/AzureIoTHub.Portal.Server/Services/DeviceModelService.cs | 2 ++ src/AzureIoTHub.Portal.Server/Services/EdgeModelService.cs | 2 +- 3 files changed, 5 insertions(+), 1 deletion(-) diff --git a/src/AzureIoTHub.Portal.Application/Managers/IDeviceModelImageManager.cs b/src/AzureIoTHub.Portal.Application/Managers/IDeviceModelImageManager.cs index e386521a3..0cd808c01 100644 --- a/src/AzureIoTHub.Portal.Application/Managers/IDeviceModelImageManager.cs +++ b/src/AzureIoTHub.Portal.Application/Managers/IDeviceModelImageManager.cs @@ -18,5 +18,7 @@ public interface IDeviceModelImageManager Task InitializeDefaultImageBlob(); Task SyncImagesCacheControl(); + + Task SetDefaultImageToModel(string deviceModelId); } } diff --git a/src/AzureIoTHub.Portal.Server/Services/DeviceModelService.cs b/src/AzureIoTHub.Portal.Server/Services/DeviceModelService.cs index 125b93b88..5f5380d97 100644 --- a/src/AzureIoTHub.Portal.Server/Services/DeviceModelService.cs +++ b/src/AzureIoTHub.Portal.Server/Services/DeviceModelService.cs @@ -92,6 +92,8 @@ public async Task CreateDeviceModel(TModel deviceModel) await this.deviceModelRepository.InsertAsync(deviceModelEntity); await this.unitOfWork.SaveAsync(); + _ = this.deviceModelImageManager.SetDefaultImageToModel(deviceModel.ModelId); + await CreateDeviceModelConfiguration(deviceModel); } diff --git a/src/AzureIoTHub.Portal.Server/Services/EdgeModelService.cs b/src/AzureIoTHub.Portal.Server/Services/EdgeModelService.cs index a6486113f..6bd9d7267 100644 --- a/src/AzureIoTHub.Portal.Server/Services/EdgeModelService.cs +++ b/src/AzureIoTHub.Portal.Server/Services/EdgeModelService.cs @@ -125,7 +125,7 @@ public async Task CreateDefaultImageToEdgeModel(IoTEdgeModel edgeModel) throw new ResourceAlreadyExistsException($"The edge model with id {edgeModel?.ModelId} already exists"); } - this.deviceModelImageManager.SetDefaultImageToModel(edgeModel.ModelId); + _ = this.deviceModelImageManager.SetDefaultImageToModel(edgeModel.ModelId); await SaveModuleCommands(edgeModel); await this.configService.RollOutEdgeModelConfiguration(edgeModel); From 1dfe8a9868bd3791a5e7615dde238cbcfa0da39e Mon Sep 17 00:00:00 2001 From: crib Date: Tue, 20 Dec 2022 16:48:18 +0100 Subject: [PATCH 3/6] Test createDeviceModelShouldCreateDeviceModel --- .../Managers/DeviceModelImageManager.cs | 2 +- .../Services/EdgeModelService.cs | 26 ------------------- .../Services/DeviceModelServiceTests.cs | 5 ++++ 3 files changed, 6 insertions(+), 27 deletions(-) diff --git a/src/AzureIoTHub.Portal.Infrastructure/Managers/DeviceModelImageManager.cs b/src/AzureIoTHub.Portal.Infrastructure/Managers/DeviceModelImageManager.cs index a408f2053..00ef9f75f 100644 --- a/src/AzureIoTHub.Portal.Infrastructure/Managers/DeviceModelImageManager.cs +++ b/src/AzureIoTHub.Portal.Infrastructure/Managers/DeviceModelImageManager.cs @@ -63,7 +63,7 @@ public async Task SetDefaultImageToModel(string deviceModelId) var currentAssembly = Assembly.GetExecutingAssembly(); - using var defaultImageStream = currentAssembly + var defaultImageStream = currentAssembly .GetManifestResourceStream($"{currentAssembly.GetName().Name}.Resources.{this.deviceModelImageOptions.Value.DefaultImageName}"); _ = await blobClient.UploadAsync(defaultImageStream, true); diff --git a/src/AzureIoTHub.Portal.Server/Services/EdgeModelService.cs b/src/AzureIoTHub.Portal.Server/Services/EdgeModelService.cs index 6bd9d7267..45c74ca9c 100644 --- a/src/AzureIoTHub.Portal.Server/Services/EdgeModelService.cs +++ b/src/AzureIoTHub.Portal.Server/Services/EdgeModelService.cs @@ -99,32 +99,6 @@ public async Task CreateEdgeModel(IoTEdgeModel edgeModel) throw new ResourceAlreadyExistsException($"The edge model with id {edgeModel?.ModelId} already exists"); } - await SaveModuleCommands(edgeModel); - await this.configService.RollOutEdgeModelConfiguration(edgeModel); - } - - /// - /// Create a new edge model template and roll out - /// the edge model configuration. - /// - /// the new edge modle object. - /// nothing. - /// If edge model template already exist return ResourceAlreadyExistsException. - /// - public async Task CreateDefaultImageToEdgeModel(IoTEdgeModel edgeModel) - { - 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"); - } - _ = this.deviceModelImageManager.SetDefaultImageToModel(edgeModel.ModelId); await SaveModuleCommands(edgeModel); diff --git a/src/AzureIoTHub.Portal.Tests.Unit/Server/Services/DeviceModelServiceTests.cs b/src/AzureIoTHub.Portal.Tests.Unit/Server/Services/DeviceModelServiceTests.cs index f291aa176..6d7d9e5cc 100644 --- a/src/AzureIoTHub.Portal.Tests.Unit/Server/Services/DeviceModelServiceTests.cs +++ b/src/AzureIoTHub.Portal.Tests.Unit/Server/Services/DeviceModelServiceTests.cs @@ -145,6 +145,7 @@ public async Task CreateDeviceModelShouldCreateDeviceModel() { // Arrange var deviceModelDto = Fixture.Create(); + var expectedAvatarUrl = Fixture.Create(); _ = this.mockDeviceModelRepository.Setup(repository => repository.InsertAsync(It.IsAny())) .Returns(Task.CompletedTask); @@ -166,6 +167,10 @@ public async Task CreateDeviceModelShouldCreateDeviceModel() It.IsAny>())) .Returns(Task.CompletedTask); + _ = this.mockDeviceModelImageManager.Setup(manager => + manager.SetDefaultImageToModel(deviceModelDto.ModelId)) + .ReturnsAsync(expectedAvatarUrl); + // Act await this.deviceModelService.CreateDeviceModel(deviceModelDto); From 23e986fe41fa228f05e56342fe92e90bcc042031 Mon Sep 17 00:00:00 2001 From: crib Date: Tue, 20 Dec 2022 17:28:34 +0100 Subject: [PATCH 4/6] Test ChangeDeviceModelImageShouldSetDefaultImageToModel --- .../Managers/DeviceModelImageManagerTest.cs | 48 +++++++++++++++++++ 1 file changed, 48 insertions(+) diff --git a/src/AzureIoTHub.Portal.Tests.Unit/Infrastructure/Managers/DeviceModelImageManagerTest.cs b/src/AzureIoTHub.Portal.Tests.Unit/Infrastructure/Managers/DeviceModelImageManagerTest.cs index 5d8e16208..ebd00b1d1 100644 --- a/src/AzureIoTHub.Portal.Tests.Unit/Infrastructure/Managers/DeviceModelImageManagerTest.cs +++ b/src/AzureIoTHub.Portal.Tests.Unit/Infrastructure/Managers/DeviceModelImageManagerTest.cs @@ -103,6 +103,54 @@ public async Task ChangeDeviceModelImageShouldUploadImageAndReturnItsUri() MockRepository.VerifyAll(); } + [Test] + public async Task ChangeDeviceModelImageShouldSetDefaultImageToModel() + { + // Arrange + var deviceModelId = Fixture.Create(); + var expectedImageUri = Fixture.Create(); + using var imageAsMemoryStream = new MemoryStream(Encoding.UTF8.GetBytes(Fixture.Create())); + + var mockOptions = new DeviceModelImageOptions() + { + BaseUri = Fixture.Create() + }; + + _ = this.mockDeviceModelImageOptions.Setup(x => x.Value).Returns(mockOptions); + + _ = this.mockBlobServiceClient + .Setup(x => x.GetBlobContainerClient(It.IsAny())) + .Returns(this.mockBlobContainerClient.Object); + + _ = this.mockBlobContainerClient + .Setup(x => x.GetBlobClient(deviceModelId)) + .Returns(this.mockBlobClient.Object); + + _ = this.mockBlobClient + .Setup(client => + client.SetHttpHeadersAsync(It.IsAny(), It.IsAny(), It.IsAny())) + .ReturnsAsync(Response.FromValue(BlobsModelFactory.BlobInfo(ETag.All, DateTimeOffset.Now), Mock.Of())); + + _ = this.mockBlobClient + .Setup(client => client.UploadAsync(It.IsAny(), true, It.IsAny())) + .ReturnsAsync(Response.FromValue( + BlobsModelFactory.BlobContentInfo(ETag.All, DateTimeOffset.Now, Array.Empty(), string.Empty, + 1L), Mock.Of())); + + _ = this.mockBlobClient + .Setup(client => client.Uri) + .Returns(expectedImageUri); + + _ = this.mockConfigHandler.Setup(handler => handler.StorageAccountDeviceModelImageMaxAge).Returns(3600); + + // Act + var result = await this.deviceModelImageManager.SetDefaultImageToModel(deviceModelId); + + // Assert + _ = result.Should().Be(expectedImageUri.ToString()); + MockRepository.VerifyAll(); + } + [Test] public async Task WhenDeleteAsyncFailedDeleteDeviceModelImageAsyncShouldThrowAnInternalServerErrorException() { From c9a47de574ef5d5d283abc5c9902819aed2393a5 Mon Sep 17 00:00:00 2001 From: crib Date: Wed, 21 Dec 2022 10:42:46 +0100 Subject: [PATCH 5/6] Test CreateEdgeModelShouldCreateEdgeModel --- src/AzureIoTHub.Portal.Server/Services/EdgeModelService.cs | 2 +- .../Server/Services/EdgeModelServiceTest.cs | 5 +++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/src/AzureIoTHub.Portal.Server/Services/EdgeModelService.cs b/src/AzureIoTHub.Portal.Server/Services/EdgeModelService.cs index 45c74ca9c..da247818b 100644 --- a/src/AzureIoTHub.Portal.Server/Services/EdgeModelService.cs +++ b/src/AzureIoTHub.Portal.Server/Services/EdgeModelService.cs @@ -99,7 +99,7 @@ public async Task CreateEdgeModel(IoTEdgeModel edgeModel) throw new ResourceAlreadyExistsException($"The edge model with id {edgeModel?.ModelId} already exists"); } - _ = this.deviceModelImageManager.SetDefaultImageToModel(edgeModel.ModelId); + _ = await this.deviceModelImageManager.SetDefaultImageToModel(edgeModel?.ModelId); await SaveModuleCommands(edgeModel); await this.configService.RollOutEdgeModelConfiguration(edgeModel); diff --git a/src/AzureIoTHub.Portal.Tests.Unit/Server/Services/EdgeModelServiceTest.cs b/src/AzureIoTHub.Portal.Tests.Unit/Server/Services/EdgeModelServiceTest.cs index ba8eabb24..cf8b9f74f 100644 --- a/src/AzureIoTHub.Portal.Tests.Unit/Server/Services/EdgeModelServiceTest.cs +++ b/src/AzureIoTHub.Portal.Tests.Unit/Server/Services/EdgeModelServiceTest.cs @@ -180,6 +180,7 @@ public async Task CreateEdgeModelShouldCreateEdgeModel() { // Arrange var edgeDeviceModel = Fixture.Create(); + var expectedImageUri = Fixture.Create(); _ = this.mockEdgeDeviceModelRepository.Setup(x => x.GetByIdAsync(It.IsAny())) .ReturnsAsync((EdgeDeviceModel)null); @@ -202,6 +203,10 @@ public async Task CreateEdgeModelShouldCreateEdgeModel() _ = this.mockConfigService.Setup(x => x.RollOutEdgeModelConfiguration(It.IsAny())) .Returns(Task.CompletedTask); + _ = this.mockDeviceModelImageManager.Setup(manager => + manager.SetDefaultImageToModel(It.IsAny())) + .ReturnsAsync(expectedImageUri.ToString()); + // Act await this.edgeDeviceModelService.CreateEdgeModel(edgeDeviceModel); From 9064d9972ec14d41bd78ace502409e12846c592e Mon Sep 17 00:00:00 2001 From: Hocine Hacherouf Date: Wed, 21 Dec 2022 11:10:29 +0100 Subject: [PATCH 6/6] Remove unused nuget ref to Microsoft.Extensions.Logging.Abstractions --- .../AzureIoTHub.Portal.Infrastructure.csproj | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/AzureIoTHub.Portal.Infrastructure/AzureIoTHub.Portal.Infrastructure.csproj b/src/AzureIoTHub.Portal.Infrastructure/AzureIoTHub.Portal.Infrastructure.csproj index ba1c7d5d4..309355960 100644 --- a/src/AzureIoTHub.Portal.Infrastructure/AzureIoTHub.Portal.Infrastructure.csproj +++ b/src/AzureIoTHub.Portal.Infrastructure/AzureIoTHub.Portal.Infrastructure.csproj @@ -1,4 +1,4 @@ - + net7.0 @@ -131,7 +131,6 @@ -