Skip to content

Commit

Permalink
[Discovery.AwsApi] Add Akka.Hosting extension methods (#818)
Browse files Browse the repository at this point in the history
* Add Akka.Hosting extensions to EC2

* Add Akka.Hosting extension methods to ECS

* Update ECS integration sample project

* Bump .NET version from net5.0 to net6.0
  • Loading branch information
Arkatufus committed Sep 8, 2022
1 parent 38940f1 commit 1f6f12d
Show file tree
Hide file tree
Showing 13 changed files with 345 additions and 46 deletions.
4 changes: 2 additions & 2 deletions build-system/azure-pipeline.template.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,9 @@ jobs:
submodules: recursive # set to 'true' for a single level of submodules or 'recursive' to get submodules of submodules
persistCredentials: true
- task: UseDotNet@2
displayName: 'Use .NET 5 SDK 5.0'
displayName: 'Use .NET 6 SDK 6.0'
inputs:
version: 5.0.x
version: 6.0.x
- task: UseDotNet@2
displayName: 'Use .NET Core SDK 3.1'
inputs:
Expand Down
2 changes: 1 addition & 1 deletion build.fsx
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ let outputNuGet = output @@ "nuget"
// Configuration values for tests
let testNetFrameworkVersion = "net471"
let testNetCoreVersion = "netcoreapp3.1"
let testNetVersion = "net5.0"
let testNetVersion = "net6.0"

Target "Clean" (fun _ ->
ActivateFinalTarget "KillCreatedProcesses"
Expand Down
4 changes: 2 additions & 2 deletions src/Directory.Build.props
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,9 @@ Update all AWSSDK versions</PackageReleaseNotes>
<PropertyGroup>
<AkkaPackageTags>akka;actors;actor model;Akka;concurrency;service discovery;cluster;clustering;</AkkaPackageTags>
<LibraryFramework>netstandard2.0</LibraryFramework>
<NetFramework>net5.0</NetFramework>
<NetFramework>net6.0</NetFramework>
<TestsNetCoreFramework>netcoreapp3.1</TestsNetCoreFramework>
<TestsNet>net5.0</TestsNet>
<TestsNet>net6.0</TestsNet>
<XunitVersion>2.4.2</XunitVersion>
<XUnitRunnerVersion>2.4.3</XUnitRunnerVersion>
<CoverletVersion>3.1.2</CoverletVersion>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@

<ItemGroup>
<PackageReference Include="Akka.Discovery" Version="$(AkkaVersion)" />
<PackageReference Include="Akka.Hosting" Version="$(AkkaHostingVersion)" />
<PackageReference Include="AWSSDK.EC2" Version="3.7.83.5" />
<PackageReference Include="AWSSDK.ECS" Version="3.7.5.71" />
</ItemGroup>
Expand Down
131 changes: 131 additions & 0 deletions src/discovery/aws/Akka.Discovery.AwsApi/Ec2/AkkaHostingExtensions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
// -----------------------------------------------------------------------
// <copyright file="AkkaHostingExtensions.cs" company="Akka.NET Project">
// Copyright (C) 2009-2022 Lightbend Inc. <http://www.lightbend.com>
// Copyright (C) 2013-2022 .NET Foundation <https://github.com/akkadotnet/akka.net>
// </copyright>
// -----------------------------------------------------------------------

using System;
using Akka.Actor;
using Akka.Hosting;

namespace Akka.Discovery.AwsApi.Ec2
{
public static class AkkaHostingExtensions
{
/// <summary>
/// Adds Akka.Discovery.AwsApi.Ec2 support to the <see cref="ActorSystem"/>.
/// Note that this only adds the discovery plugin, you will still need to add ClusterBootstrap for
/// a complete solution.
/// </summary>
/// <param name="builder">
/// The builder instance being configured.
/// </param>
/// <returns>
/// The same <see cref="AkkaConfigurationBuilder"/> instance originally passed in.
/// </returns>
/// <example>
/// <code>
/// services.AddAkka("mySystem", builder => {
/// builder
/// .WithClustering()
/// .WithClusterBootstrap(setup =>
/// {
/// setup.ContactPointDiscovery.ServiceName = "testService";
/// setup.ContactPointDiscovery.RequiredContactPointsNr = 1;
/// }, autoStart: true)
/// .WithAwsEc2Discovery();
/// }
/// </code>
/// </example>
public static AkkaConfigurationBuilder WithAwsEc2Discovery(this AkkaConfigurationBuilder builder)
=> builder.WithAwsEc2Discovery(new Ec2ServiceDiscoverySetup());

/// <summary>
/// Adds Akka.Discovery.AwsApi.Ec2 support to the <see cref="ActorSystem"/>.
/// Note that this only adds the discovery plugin, you will still need to add ClusterBootstrap for
/// a complete solution.
/// </summary>
/// <param name="builder">
/// The builder instance being configured.
/// </param>
/// <param name="configure">
/// An action that modifies an <see cref="Ec2ServiceDiscoverySetup"/> instance, used
/// to configure Akka.Discovery.AwsApi.Ec2.
/// </param>
/// <returns>
/// The same <see cref="AkkaConfigurationBuilder"/> instance originally passed in.
/// </returns>
/// <example>
/// <code>
/// services.AddAkka("mySystem", builder => {
/// builder
/// .WithClustering()
/// .WithClusterBootstrap(setup =>
/// {
/// setup.ContactPointDiscovery.ServiceName = "testService";
/// setup.ContactPointDiscovery.RequiredContactPointsNr = 1;
/// }, autoStart: true)
/// .WithAwsEc2Discovery(setup => {
/// setup.WithCredentialProvider&lt;AnonymousEc2CredentialProvider&gt;();
/// setup.TagKey = "myTag";
/// });
/// }
/// </code>
/// </example>
public static AkkaConfigurationBuilder WithAwsEc2Discovery(
this AkkaConfigurationBuilder builder,
Action<Ec2ServiceDiscoverySetup> configure)
{
var setup = new Ec2ServiceDiscoverySetup();
configure(setup);
return builder.WithAwsEc2Discovery(setup);
}

/// <summary>
/// Adds Akka.Discovery.AwsApi.Ec2 support to the <see cref="ActorSystem"/>.
/// Note that this only adds the discovery plugin, you will still need to add ClusterBootstrap for
/// a complete solution.
/// </summary>
/// <param name="builder">
/// The builder instance being configured.
/// </param>
/// <param name="setup">
/// The <see cref="Ec2ServiceDiscoverySetup"/> instance used to configure Akka.Discovery.Azure.
/// </param>
/// <returns>
/// The same <see cref="AkkaConfigurationBuilder"/> instance originally passed in.
/// </returns>
/// <example>
/// <code>
/// services.AddAkka("mySystem", builder => {
/// builder
/// .WithClustering()
/// .WithClusterBootstrap(setup =>
/// {
/// setup.ContactPointDiscovery.ServiceName = "testService";
/// setup.ContactPointDiscovery.RequiredContactPointsNr = 1;
/// }, autoStart: true)
/// .WithAwsEc2Discovery(setup => {
/// setup.WithCredentialProvider&lt;AnonymousEc2CredentialProvider&gt;();
/// setup.TagKey = "myTag";
/// });
/// }
/// </code>
/// </example>
public static AkkaConfigurationBuilder WithAwsEc2Discovery(
this AkkaConfigurationBuilder builder,
Ec2ServiceDiscoverySetup setup)
{
builder.AddHocon("akka.discovery.method = aws-api-ec2-tag-based", HoconAddMode.Prepend);
builder.AddSetup(setup);

// force start the module
builder.AddStartup((system, registry) =>
{
AwsEc2Discovery.Get(system);
});
return builder;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
using System.Collections.Generic;
using System.Collections.Immutable;
using Akka.Actor.Setup;
using Akka.Configuration;
using Amazon.EC2;
using Amazon.EC2.Model;

Expand All @@ -17,10 +18,30 @@ namespace Akka.Discovery.AwsApi.Ec2
public sealed class Ec2ServiceDiscoverySetup : Setup
{
private Type _clientConfig;
public Type ClientConfig => _clientConfig;

public Type ClientConfig
{
get => _clientConfig;
set
{
if (value != null && !typeof(AmazonEC2Config).IsAssignableFrom(value))
throw new ConfigurationException($"{nameof(ClientConfig)} Type value need to extend {nameof(AmazonEC2Config)}. Was: {value.Name}");
_clientConfig = value;
}
}

private Type _credProvider;
public Type CredentialsProvider => _credProvider;
public Type CredentialsProvider
{
get => _credProvider;
set
{
if (value != null && !typeof(Ec2CredentialProvider).IsAssignableFrom(value))
throw new ConfigurationException($"{nameof(CredentialsProvider)} Type value need to extend {nameof(Ec2CredentialProvider)}. Was: {value.Name}");
_credProvider = value;
}
}

public string TagKey { get; set; }
public List<Filter> Filters { get; set; }
public List<int> Ports { get; set; }
Expand All @@ -29,13 +50,13 @@ public sealed class Ec2ServiceDiscoverySetup : Setup

public Ec2ServiceDiscoverySetup WithClientConfig<T>() where T: AmazonEC2Config
{
_clientConfig = typeof(T);
ClientConfig = typeof(T);
return this;
}

public Ec2ServiceDiscoverySetup WithCredentialProvider<T>() where T : Ec2CredentialProvider
{
_credProvider = typeof(T);
CredentialsProvider = typeof(T);
return this;
}

Expand Down
153 changes: 153 additions & 0 deletions src/discovery/aws/Akka.Discovery.AwsApi/Ecs/AkkaHostingExtensions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,153 @@
// -----------------------------------------------------------------------
// <copyright file="AkkaHostingExtensions.cs" company="Akka.NET Project">
// Copyright (C) 2009-2022 Lightbend Inc. <http://www.lightbend.com>
// Copyright (C) 2013-2022 .NET Foundation <https://github.com/akkadotnet/akka.net>
// </copyright>
// -----------------------------------------------------------------------

using System;
using System.Collections.Generic;
using Akka.Actor;
using Akka.Hosting;
using Amazon.ECS.Model;

namespace Akka.Discovery.AwsApi.Ecs
{
public static class AkkaHostingExtensions
{
/// <summary>
/// Adds Akka.Discovery.AwsApi.Ecs support to the <see cref="ActorSystem"/>.
/// Note that this only adds the discovery plugin, you will still need to add ClusterBootstrap for
/// a complete solution.
/// </summary>
/// <param name="builder">
/// The builder instance being configured.
/// </param>
/// <param name="clusterName">
/// <para>
/// Optional. The name of the AWS ECS cluster.
/// </para>
/// <b>Default</b>: "default"
/// </param>
/// <param name="tags">
/// <para>
/// Optional. A list of <see cref="Tag"/> used to filter the ECS cluster tasks.
/// The task must have the same exact list of tags to be considered as potential contact point by the
/// discovery module.
/// </para>
/// <b>Default</b>: empty list.
/// </param>
/// <returns>
/// The same <see cref="AkkaConfigurationBuilder"/> instance originally passed in.
/// </returns>
/// <example>
/// <code>
/// services.AddAkka("mySystem", builder => {
/// builder
/// .WithClustering()
/// .WithClusterBootstrap(setup =>
/// {
/// setup.ContactPointDiscovery.ServiceName = "testService";
/// setup.ContactPointDiscovery.RequiredContactPointsNr = 1;
/// }, autoStart: true)
/// .WithAwsEcsDiscovery();
/// }
/// </code>
/// </example>
public static AkkaConfigurationBuilder WithAwsEcsDiscovery(
this AkkaConfigurationBuilder builder,
string clusterName = null,
IEnumerable<Tag> tags = null)
=> builder.WithAwsEcsDiscovery(new EcsServiceDiscoverySetup
{
Cluster = clusterName,
Tags = tags
});

/// <summary>
/// Adds Akka.Discovery.AwsApi.Ec2 support to the <see cref="ActorSystem"/>.
/// Note that this only adds the discovery plugin, you will still need to add ClusterBootstrap for
/// a complete solution.
/// </summary>
/// <param name="builder">
/// The builder instance being configured.
/// </param>
/// <param name="configure">
/// An action that modifies an <see cref="EcsServiceDiscoverySetup"/> instance, used
/// to configure Akka.Discovery.AwsApi.Ec2.
/// </param>
/// <returns>
/// The same <see cref="AkkaConfigurationBuilder"/> instance originally passed in.
/// </returns>
/// <example>
/// <code>
/// services.AddAkka("mySystem", builder => {
/// builder
/// .WithClustering()
/// .WithClusterBootstrap(setup =>
/// {
/// setup.ContactPointDiscovery.ServiceName = "testService";
/// setup.ContactPointDiscovery.RequiredContactPointsNr = 1;
/// }, autoStart: true)
/// .WithAwsEcsDiscovery(setup => {
/// setup.Cluster = "my-ecs-cluster-name";
/// });
/// }
/// </code>
/// </example>
public static AkkaConfigurationBuilder WithAwsEcsDiscovery(
this AkkaConfigurationBuilder builder,
Action<EcsServiceDiscoverySetup> configure)
{
var setup = new EcsServiceDiscoverySetup();
configure(setup);
return builder.WithAwsEcsDiscovery(setup);
}

/// <summary>
/// Adds Akka.Discovery.AwsApi.Ec2 support to the <see cref="ActorSystem"/>.
/// Note that this only adds the discovery plugin, you will still need to add ClusterBootstrap for
/// a complete solution.
/// </summary>
/// <param name="builder">
/// The builder instance being configured.
/// </param>
/// <param name="setup">
/// The <see cref="EcsServiceDiscoverySetup"/> instance used to configure Akka.Discovery.Azure.
/// </param>
/// <returns>
/// The same <see cref="AkkaConfigurationBuilder"/> instance originally passed in.
/// </returns>
/// <example>
/// <code>
/// services.AddAkka("mySystem", builder => {
/// builder
/// .WithClustering()
/// .WithClusterBootstrap(setup =>
/// {
/// setup.ContactPointDiscovery.ServiceName = "testService";
/// setup.ContactPointDiscovery.RequiredContactPointsNr = 1;
/// }, autoStart: true)
/// .WithAwsEcsDiscovery(new EcsServiceDiscoverySetup {
/// Cluster = "my-ecs-cluster-name"
/// });
/// }
/// </code>
/// </example>
public static AkkaConfigurationBuilder WithAwsEcsDiscovery(
this AkkaConfigurationBuilder builder,
EcsServiceDiscoverySetup setup)
{
builder.AddHocon("akka.discovery.method = aws-api-ecs", HoconAddMode.Prepend);
builder.AddSetup(setup);

// force start the module
builder.AddStartup((system, registry) =>
{
AwsEcsDiscovery.Get(system);
});
return builder;
}

}
}

0 comments on commit 1f6f12d

Please sign in to comment.