Skip to content

Commit

Permalink
#2169 improve aws exceptions management (#2207)
Browse files Browse the repository at this point in the history
* Improve AWS exceptions (1)

* improve AWS exceptions (2)

* delete using

* Improve AWS exceptions (3)

* delete unused using instructions

* fix some code scanning warning

* fixed

* Failed tests to fix

* Improve AWS Exception

* Fix some warnings

* Update AWSEdgeDevicesService.cs

* DeleteDynamicGroups when deleting thing type
  • Loading branch information
ssgueye2 authored and kbeaugrand committed Jun 23, 2023
1 parent b2fd244 commit 7d1c067
Show file tree
Hide file tree
Showing 13 changed files with 764 additions and 456 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -89,31 +89,44 @@ private async Task<List<IoTEdgeModel>> GetAllGreenGrassDeployments()
HistoryFilter = DeploymentHistoryFilter.LATEST_ONLY
};

var response = await this.amazonGreenGrass.ListDeploymentsAsync(request);

foreach (var deployment in response.Deployments)
try
{
var awsThingGroupRegex = new Regex(@"/([^/]+)$");
var matches = awsThingGroupRegex.Match(deployment.TargetArn);
var response = await this.amazonGreenGrass.ListDeploymentsAsync(request);

if (matches.Success && matches.Groups.Count > 1)
foreach (var deployment in response.Deployments)
{
var thinggroupName = matches.Groups[1].Value;
var s = await this.amazonIoTClient.DescribeThingGroupAsync(new Amazon.IoT.Model.DescribeThingGroupRequest { ThingGroupName = thinggroupName });
if (s.QueryString != null)
var awsThingGroupRegex = new Regex(@"/([^/]+)$");
var matches = awsThingGroupRegex.Match(deployment.TargetArn);

if (matches.Success && matches.Groups.Count > 1)
{
var iotEdgeModel = new IoTEdgeModel
var thinggroupName = matches.Groups[1].Value;
try
{
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);
}
}
catch (AmazonIoTException e)
{
ModelId = deployment.DeploymentId, //Instead of giving a random Id here, we can give the deploymentID
Name = deployment.DeploymentName,
ExternalIdentifier = deployment.DeploymentId
};
deployments.Add(iotEdgeModel);
throw new Domain.Exceptions.InternalServerErrorException("Unable to Describe The thing group due to an error in the Amazon IoT API.", e);
}
}
}
nextToken = response.NextToken;
}
catch (AmazonGreengrassV2Exception e)
{
throw new Domain.Exceptions.InternalServerErrorException("Unable to List The deployments due to an error in the Amazon IoT API.", e);
}

nextToken = response.NextToken;
}
while (!string.IsNullOrEmpty(nextToken));

Expand Down
54 changes: 40 additions & 14 deletions src/IoTHub.Portal.Infrastructure/Jobs/AWS/SyncThingTypesJob.cs
Original file line number Diff line number Diff line change
Expand Up @@ -94,13 +94,25 @@ private async Task<List<DescribeThingTypeResponse>> Remove5mnDeprecatedThingType

foreach (var thingType in thingTypes)
{
var diffInMinutes = (DateTime.Now.Subtract(thingType.ThingTypeMetadata.DeprecationDate)).TotalMinutes;
var diffInMinutes = DateTime.Now.Subtract(thingType.ThingTypeMetadata.DeprecationDate).TotalMinutes;
if (thingType.ThingTypeMetadata.Deprecated && diffInMinutes > 5)
{
_ = await this.amazonIoTClient.DeleteThingTypeAsync(new DeleteThingTypeRequest
try
{
ThingTypeName = thingType.ThingTypeName
});
_ = await this.amazonIoTClient.DeleteThingTypeAsync(new DeleteThingTypeRequest
{
ThingTypeName = thingType.ThingTypeName
});

_ = await this.amazonIoTClient.DeleteDynamicThingGroupAsync(new DeleteDynamicThingGroupRequest
{
ThingGroupName = thingType.ThingTypeName
});
}
catch (AmazonIoTException e)
{
throw new Domain.Exceptions.InternalServerErrorException("Unable to Delete The thing type due to an error in the Amazon IoT API.", e);
}
}
else
{
Expand All @@ -123,19 +135,33 @@ private async Task<List<DescribeThingTypeResponse>> GetAllThingTypes()
NextToken = nextToken
};

var response = await amazonIoTClient.ListThingTypesAsync(request);

foreach (var thingType in response.ThingTypes)
try
{
var requestDescribeThingType = new DescribeThingTypeRequest
{
ThingTypeName = thingType.ThingTypeName,
};
var response = await amazonIoTClient.ListThingTypesAsync(request);

thingTypes.Add(await this.amazonIoTClient.DescribeThingTypeAsync(requestDescribeThingType));
foreach (var thingType in response.ThingTypes)
{
var requestDescribeThingType = new DescribeThingTypeRequest
{
ThingTypeName = thingType.ThingTypeName,
};

try
{
thingTypes.Add(await this.amazonIoTClient.DescribeThingTypeAsync(requestDescribeThingType));
}
catch (AmazonIoTException e)
{
throw new Domain.Exceptions.InternalServerErrorException("Unable to Describe The thing type due to an error in the Amazon IoT API.", e);
}
}

nextToken = response.NextToken;
}
catch (AmazonIoTException e)
{
throw new Domain.Exceptions.InternalServerErrorException("Unable to list Thing types due to an error in the Amazon IoT API.", e);
}

nextToken = response.NextToken;
}
while (!string.IsNullOrEmpty(nextToken));

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ namespace IoTHub.Portal.Infrastructure.Managers
using System.Threading.Tasks;
using Amazon.S3;
using Amazon.S3.Model;
using Azure;
using IoTHub.Portal.Application.Managers;
using IoTHub.Portal.Domain;
using IoTHub.Portal.Domain.Exceptions;
Expand Down Expand Up @@ -38,39 +37,48 @@ public AwsDeviceModelImageManager(

public async Task<string> ChangeDeviceModelImageAsync(string deviceModelId, Stream stream)
{
this.logger.LogInformation($"Uploading Image to AWS S3 storage");

this.logger.LogInformation($"Uploading Image to AWS S3 storage");

//Portal must be able to upload images to Amazon S3
var putObjectRequest = new PutObjectRequest
{
BucketName = this.configHandler.AWSBucketName,
Key = deviceModelId,
InputStream = stream,
ContentType = "image/*",
Headers = {CacheControl = $"max-age={this.configHandler.StorageAccountDeviceModelImageMaxAge}, must-revalidate" }
};
var putObjectResponse = await this.s3Client.PutObjectAsync(putObjectRequest);

if (putObjectResponse.HttpStatusCode == System.Net.HttpStatusCode.OK)
try
{
//Images on S3 are publicly accessible and read-only
var putAclRequest = new PutACLRequest
//Portal must be able to upload images to Amazon S3
var putObjectRequest = new PutObjectRequest
{
BucketName = this.configHandler.AWSBucketName,
Key = deviceModelId,
CannedACL = S3CannedACL.PublicRead // Set the object's ACL to public read
InputStream = stream,
ContentType = "image/*",
Headers = {CacheControl = $"max-age={this.configHandler.StorageAccountDeviceModelImageMaxAge}, must-revalidate" }
};
var putACLResponse = await this.s3Client.PutACLAsync(putAclRequest);

return putACLResponse.HttpStatusCode == System.Net.HttpStatusCode.OK
? ComputeImageUri(deviceModelId).ToString()
: throw new InternalServerErrorException("Error by setting the image access to public and read-only");
_ = await this.s3Client.PutObjectAsync(putObjectRequest);

try
{
//Images on S3 are publicly accessible and read-only
var putAclRequest = new PutACLRequest
{
BucketName = this.configHandler.AWSBucketName,
Key = deviceModelId,
CannedACL = S3CannedACL.PublicRead // Set the object's ACL to public read
};

_ = await this.s3Client.PutACLAsync(putAclRequest);

return ComputeImageUri(deviceModelId).ToString();
}
catch (AmazonS3Exception e)
{
throw new InternalServerErrorException("Unable to set the image access to public and read-only due to an error in Amazon S3 API.", e);
}

}
else
catch (AmazonS3Exception e)
{
throw new InternalServerErrorException("Error by uploading the image in S3 Storage");
throw new InternalServerErrorException(" Unable to upload the image in S3 Bucket due to an error in Amazon S3 API.", e);
}

}

public Uri ComputeImageUri(string deviceModelId)
Expand All @@ -84,61 +92,68 @@ public async Task DeleteDeviceModelImageAsync(string deviceModelId)

this.logger.LogInformation($"Deleting image from AWS S3 storage");

var deleteImageObject = new DeleteObjectRequest
{
BucketName = this.configHandler.AWSBucketName,
Key = deviceModelId
};
try
{
var deleteImageObject = new DeleteObjectRequest
{
BucketName = this.configHandler.AWSBucketName,
Key = deviceModelId
};

_ = await this.s3Client.DeleteObjectAsync(deleteImageObject);

}
catch (RequestFailedException e)
catch (AmazonS3Exception e)
{
throw new InternalServerErrorException("Unable to delete the image from S3 storage.", e);
throw new InternalServerErrorException("Unable to delete the image from S3 storage due to an error in Amazon S3 API.", e);
}
}

public async Task<string> SetDefaultImageToModel(string deviceModelId)
{

this.logger.LogInformation($"Uploading Default Image to AWS S3 storage");

var currentAssembly = Assembly.GetExecutingAssembly();
var defaultImageStream = currentAssembly
.GetManifestResourceStream($"{currentAssembly.GetName().Name}.Resources.{this.imageOptions.Value.DefaultImageName}");


//Portal must be able to upload images to Amazon S3
var putObjectRequest = new PutObjectRequest
{
BucketName = this.configHandler.AWSBucketName,
Key = deviceModelId,
InputStream = defaultImageStream,
ContentType = "image/*", // image content type
Headers = {CacheControl = $"max-age={this.configHandler.StorageAccountDeviceModelImageMaxAge}, must-revalidate" }

};

var putObjectResponse = await this.s3Client.PutObjectAsync(putObjectRequest);

if (putObjectResponse.HttpStatusCode == System.Net.HttpStatusCode.OK)
try
{
//Images on S3 are publicly accessible and read-only
var putAclRequest = new PutACLRequest
//Portal must be able to upload images to Amazon S3
var putObjectRequest = new PutObjectRequest
{
BucketName = this.configHandler.AWSBucketName,
Key = deviceModelId,
CannedACL = S3CannedACL.PublicRead // Set the object's ACL to public read
InputStream = defaultImageStream,
ContentType = "image/*", // image content type
Headers = {CacheControl = $"max-age={this.configHandler.StorageAccountDeviceModelImageMaxAge}, must-revalidate" }

};
var putACLResponse = await this.s3Client.PutACLAsync(putAclRequest);

return putACLResponse.HttpStatusCode == System.Net.HttpStatusCode.OK
? ComputeImageUri(deviceModelId).ToString()
: throw new InternalServerErrorException("Error by setting the image access to public and read-only");
_ = await this.s3Client.PutObjectAsync(putObjectRequest);

try
{
//Images on S3 are publicly accessible and read-only
var putAclRequest = new PutACLRequest
{
BucketName = this.configHandler.AWSBucketName,
Key = deviceModelId,
CannedACL = S3CannedACL.PublicRead // Set the object's ACL to public read
};
_ = await this.s3Client.PutACLAsync(putAclRequest);

return ComputeImageUri(deviceModelId).ToString();
}
catch (AmazonS3Exception e)
{
throw new InternalServerErrorException("Unable to set the image access to public and read-only due to an error in Amazon S3 API.", e);
}
}
else
catch (AmazonS3Exception e)
{
throw new InternalServerErrorException("Error by uploading the image in S3 Storage");
throw new InternalServerErrorException("Unable to upload the image in S3 Bucket due to an error in Amazon S3 API.", e);
}

}
Expand All @@ -152,37 +167,41 @@ public async Task InitializeDefaultImageBlob()

var defaultImageStream = currentAssembly
.GetManifestResourceStream($"{currentAssembly.GetName().Name}.Resources.{this.imageOptions.Value.DefaultImageName}");
var putObjectRequest = new PutObjectRequest
{
BucketName = this.configHandler.AWSBucketName,
Key = this.imageOptions.Value.DefaultImageName,
InputStream = defaultImageStream,
ContentType = "image/*", // image content type
Headers = {CacheControl = $"max-age={this.configHandler.StorageAccountDeviceModelImageMaxAge}, must-revalidate" }

};

var putObjectResponse = await this.s3Client.PutObjectAsync(putObjectRequest);

if (putObjectResponse.HttpStatusCode == System.Net.HttpStatusCode.OK)
try
{
//Images on S3 are publicly accessible and read-only
var putAclRequest = new PutACLRequest
var putObjectRequest = new PutObjectRequest
{
BucketName = this.configHandler.AWSBucketName,
Key = this.imageOptions.Value.DefaultImageName,
CannedACL = S3CannedACL.PublicRead // Set the object's ACL to public read
InputStream = defaultImageStream,
ContentType = "image/*", // image content type
Headers = {CacheControl = $"max-age={this.configHandler.StorageAccountDeviceModelImageMaxAge}, must-revalidate" }

};
var putACLResponse = await this.s3Client.PutACLAsync(putAclRequest);

if (putACLResponse.HttpStatusCode != System.Net.HttpStatusCode.OK)
_ = await this.s3Client.PutObjectAsync(putObjectRequest);

try
{
//Images on S3 are publicly accessible and read-only
var putAclRequest = new PutACLRequest
{
BucketName = this.configHandler.AWSBucketName,
Key = this.imageOptions.Value.DefaultImageName,
CannedACL = S3CannedACL.PublicRead // Set the object's ACL to public read
};

_ = await this.s3Client.PutACLAsync(putAclRequest);
}
catch (AmazonS3Exception e)
{
throw new InternalServerErrorException("Error by setting the image access to public and read-only");
throw new InternalServerErrorException("Unable to set the image access to public and read-only due to an error in Amazon S3 API.", e);
}
}
else
catch (AmazonS3Exception e)
{
throw new InternalServerErrorException("Error by uploading the image in S3 Storage");
throw new InternalServerErrorException("Unable to upload the image in S3 Bucket due to an error in Amazon S3 API.", e);
}

}
Expand Down
Loading

0 comments on commit 7d1c067

Please sign in to comment.