Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Discovery.AwsApi] Add Akka.Hosting extension methods #818

Merged
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.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
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;
}

}
}