For development, I have a number of AWS profiles, I use the AWS Profile section in appsettings.json to define the profile I want use:
"AWS": {
"Profile": "CorpAccount",
"Region": "us-east-1"
}
Since this is not the default profile, I need the context to use a named profile when I debug and run unit tests (xunit). What I'd like to know is what is the best practice to config the profile.
Here is a class that shows three approaches (two work in local):
public class EmailQueueService : IEmailQueueService
{
private IConfiguration _configuration;
private readonly ILogger _logger;
public EmailQueueService(IConfiguration configuration, ILogger<EmailQueueService> logger)
{
_configuration = configuration;
_logger = logger;
}
public async Task<bool> Add1Async(ContactFormModel contactForm)
{
var sqsClient = new AmazonSQSClient();
var sendRequest = // removed for clarity
var response = await sqsClient.SendMessageAsync(sendRequest);
return response.HttpStatusCode == System.Net.HttpStatusCode.OK;
}
public async Task<bool> Add2Async(ContactFormModel contactForm)
{
var sqsClient = _configuration.GetAWSOptions().CreateServiceClient<IAmazonSQS>();
var sendRequest = // removed for clarity
var response = await sqsClient.SendMessageAsync(sendRequest);
return response.HttpStatusCode == System.Net.HttpStatusCode.OK;
}
public async Task<bool> Add3Async(ContactFormModel contactForm)
{
var sqsClient = new AmazonSQSClient(credentials: Common.Credentials(_configuration));
var sendRequest = // removed for clarity
var response = await sqsClient.SendMessageAsync(sendRequest);
return response.HttpStatusCode == System.Net.HttpStatusCode.OK;
}
public AWSCredentials Credentials(IConfiguration config)
{
var chain = new CredentialProfileStoreChain();
if (!chain.TryGetAWSCredentials(config.GetAWSOptions().Profile, out AWSCredentials awsCredentials))
{
throw new Exception("Profile not found.");
}
return awsCredentials;
}
}
Results:
Add1Async
fails locally because it uses the default profile not the "CorpAccount".Add2Async
works locally, but is seems like an odd way to create a new instance.Add3Async
works locally, but it will likely fail when deployed becauseconfig.GetAWSOptions().Profile
doesn't exist outside of the local environment.
For completeness, here is a unit test I'm calling it from:
[Fact]
public async void AddAsyncTest()
{
// Arrange
var configuration = TestConfigure.Getconfiguration();
var service = new EmailQueueService(configuration, Mock.Of<ILogger<EmailQueueService>>());
// Act
var result = await service.AddAsync(ContactFormModelMock.GetNew());
// Assert
Assert.True(result);
}
public static IConfiguration Getconfiguration()
{
var builder = new ConfigurationBuilder()
.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
.AddEnvironmentVariables();
return builder.Build();
}