Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions src/BuslyCLI.Console/Config/AmazonsqsTransportConfig.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,11 @@

public class AmazonsqsTransportConfig : ITransportConfig
{

// Local Stack Only
public string ServiceUrl { get; set; }
public string RegionName { get; set; }
public string AccessKey { get; set; }
public string SecretKey { get; set; }

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
using FluentValidation;

namespace BuslyCLI.Config.Validators;

public class AmazonsqsTransportConfigValidator : AbstractValidator<AmazonsqsTransportConfig>
{
public AmazonsqsTransportConfigValidator()
{
RuleFor(x => x.RegionName)
.NotEmpty();

RuleFor(x => x)
.Must(x =>
(string.IsNullOrEmpty(x.AccessKey) && string.IsNullOrEmpty(x.SecretKey)) // both empty
|| (!string.IsNullOrEmpty(x.AccessKey) && !string.IsNullOrEmpty(x.SecretKey)) // both set
)
.WithMessage("AWS AccessKey and SecretKey are mutually dependent: if one is set, the other must also be set.");
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ public TransportConfigValidator()
v.Add(new LearningTransportConfigValidator());
v.Add(new RabbitMQTransportConfigValidator());
v.Add(new AzureServiceBusTransportConfigValidator());
v.Add(new AmazonsqsTransportConfigValidator());
});

// RuleFor(x => x.LearningTransportConfig)
Expand Down
31 changes: 20 additions & 11 deletions src/BuslyCLI.Console/Factories/RawEndpointFactory.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using Amazon.Runtime;
using Amazon;
using Amazon.Runtime;
using Amazon.SimpleNotificationService;
using Amazon.SQS;
using BuslyCLI.Config;
Expand Down Expand Up @@ -73,19 +74,27 @@ private static ManagementApiConfiguration CreateManagementApiConfig(ManagementAp

private TransportDefinition CreateAmazonSQSTransport(AmazonsqsTransportConfig amazonsqsTransportConfig)
{
var credentials = new BasicAWSCredentials("test", "test");

var sqsClient = new AmazonSQSClient(credentials, new AmazonSQSConfig
var credentials = new BasicAWSCredentials(amazonsqsTransportConfig.AccessKey, amazonsqsTransportConfig.SecretKey);
var amazonSqsConfig = new AmazonSQSConfig();
var amazonSnsConfig = new AmazonSimpleNotificationServiceConfig();
if (!string.IsNullOrWhiteSpace(amazonsqsTransportConfig.RegionName))
{
ServiceURL = amazonsqsTransportConfig.ServiceUrl,
AuthenticationRegion = amazonsqsTransportConfig.RegionName,
});

var snsClient = new AmazonSimpleNotificationServiceClient(credentials, new AmazonSimpleNotificationServiceConfig
amazonSqsConfig.RegionEndpoint = RegionEndpoint.GetBySystemName(amazonsqsTransportConfig.RegionName);
amazonSnsConfig.RegionEndpoint = RegionEndpoint.GetBySystemName(amazonsqsTransportConfig.RegionName);
}

// If ServiceUrl is passed, we are assuming we are using LocalStack
// Without this, local stack will try to really authenticate with aws which will fail
if (!string.IsNullOrWhiteSpace(amazonsqsTransportConfig.ServiceUrl))
{
ServiceURL = amazonsqsTransportConfig.ServiceUrl,
AuthenticationRegion = amazonsqsTransportConfig.RegionName,
});
amazonSnsConfig.ServiceURL = amazonsqsTransportConfig.ServiceUrl;
amazonSqsConfig.ServiceURL = amazonsqsTransportConfig.ServiceUrl;
}

var sqsClient = new AmazonSQSClient(credentials, amazonSqsConfig);

var snsClient = new AmazonSimpleNotificationServiceClient(credentials, amazonSnsConfig);

return new SqsTransport(sqsClient, snsClient);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
using BuslyCLI.Config;
using BuslyCLI.Config.Validators;
using FluentValidation.TestHelper;

namespace BuslyCLI.Console.Tests.Config.Validators;

[TestFixture]
public class AmazonsqsTransportConfigValidatorTests
{
private readonly AmazonsqsTransportConfigValidator _validator;

public AmazonsqsTransportConfigValidatorTests()
{
_validator = new AmazonsqsTransportConfigValidator();
}

[Test]
public async Task ShouldErrorWhenRegionNameIsNotPassed()
{
// Arrange
var amazonsqsTransportConfig = new AmazonsqsTransportConfig
{
RegionName = null
};

// Act
var result = await _validator.TestValidateAsync(amazonsqsTransportConfig);

// Assert
result.ShouldHaveValidationErrorFor(c => c.RegionName)
.WithErrorMessage("'Region Name' must not be empty.");
}

[Test]
public async Task ShouldNotErrorWhenRegionNameIsPassed()
{
// Arrange
var amazonsqsTransportConfig = new AmazonsqsTransportConfig
{
RegionName = "us-east-1"
};
// Act
var result = await _validator.TestValidateAsync(amazonsqsTransportConfig);

// Assert
result.ShouldNotHaveValidationErrorFor(c => c.RegionName);
}

[Test]
public async Task ShouldNotErrorWhenServiceUrlIsPassed()
{
// Arrange
var amazonsqsTransportConfig = new AmazonsqsTransportConfig
{
ServiceUrl = "us-east-1"
};
// Act
var result = await _validator.TestValidateAsync(amazonsqsTransportConfig);

// Assert
result.ShouldNotHaveValidationErrorFor(c => c.ServiceUrl);
}

[Test]
public async Task ShouldErrorWhenAccessKeyIsPassedWithoutSecretKey()
{
// Arrange
var amazonsqsTransportConfig = new AmazonsqsTransportConfig()
{
AccessKey = "BLAHBLAHBLAH",
SecretKey = null
};
// Act
var result = await _validator.TestValidateAsync(amazonsqsTransportConfig);

// Assert
result.ShouldHaveValidationErrors().WithErrorMessage("AWS AccessKey and SecretKey are mutually dependent: if one is set, the other must also be set.");
}

[Test]
public async Task ShouldErrorWhenSecretIsPassedWithoutAccessKey()
{
// Arrange
var amazonsqsTransportConfig = new AmazonsqsTransportConfig()
{
AccessKey = null,
SecretKey = "BLAHBLAHBLAH"
};
// Act
var result = await _validator.TestValidateAsync(amazonsqsTransportConfig);

// Assert
result.ShouldHaveValidationErrors().WithErrorMessage("AWS AccessKey and SecretKey are mutually dependent: if one is set, the other must also be set.");
}
}
88 changes: 88 additions & 0 deletions website/docs/transports/amazon-sqs.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
# Amazon SQS

The **Amazon SQS Transport** is used to communicate to Amazon SQS. It is suitable for development, testing, and production environments.

## Configuration

To use the Amazon SQS Transport, define it under `transports` and reference it as `current-transport`.

### Example

```yaml
current-transport: local-stack-amazon-sqs

transports:
- name: local-stack-amazon-sqs
amazonsqs-transport-config:
region-name: us-east-1
access-key: test
secret-key: test
service-url: http://127.0.0.1:32813/ # (optional) Only used when connecting to local-stack
```

:::info

The Amazon SQS transport implementation currently works only with **AWS access key and secret key authentication**. Pull requests that add support for additional authentication methods are welcome and greatly appreciated!

:::

---

## `amazonsqs-transport-config` Fields

| Field | Required | Type | Default | Description |
| ------------- | -------- | ------ | ------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `region-name` | **Yes** | string | — | The AWS region. All Region codes can be found [here](https://docs.aws.amazon.com/global-infrastructure/latest/regions/aws-regions.html) (EX: us-east-1, us-east2, us-west1..etc). |
| `access-key` | **Yes** | string | — | The AWS Access Key. |
| `secret-key` | **Yes** | string | — | The AWS Secret Key. |
| `service-url` | No | string | — | The service URL used to connect to LocalStack for local development. |

---

## Field Details

### `region-name` (required)

The AWS Region SQS is hosted in.

Examples:

```yaml
region-name: us-east-1
```

---

### `access-key` (required)

The AWS Access Key.

Examples:

```yaml
access-key: test
```

---

### `secret-key` (required)

The AWS Secret Key.

Examples:

```yaml
secret-key: test
```

---

### `service-url` (optional)

The service URL used to connect to LocalStack for local development.

Examples:

```yaml
service-url: http://127.0.0.1:32813/
```
2 changes: 2 additions & 0 deletions website/docs/transports/rabbitmq.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,8 @@ amqp-connection-string: amqp://guest:guest@localhost:5672/
amqp-connection-string: amqps://user:[email protected]:5671/my-vhost
```

---

### `management-api` (optional)

Allows Busly to interact with the RabbitMQ Management API for monitoring or queue management.
Expand Down