Skip to content

Commit

Permalink
Update to Durable Functions v2 (#50)
Browse files Browse the repository at this point in the history
* Update to Durable Functions v2

* Adding hubName

* Lifecycle helper using dependency injection

* Remove obsolete code

* Update to Durable Functions v2-rtm
  • Loading branch information
shibayan authored Nov 3, 2019
1 parent 09ea2c2 commit 4a6b97e
Show file tree
Hide file tree
Showing 11 changed files with 64 additions and 61 deletions.
21 changes: 12 additions & 9 deletions KeyVault.Acmebot/AddCertificateFunctions.cs
Original file line number Diff line number Diff line change
@@ -1,34 +1,37 @@
using System;
using System.Net;
using System.Net.Http;
using System.Threading.Tasks;

using KeyVault.Acmebot.Models;

using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Azure.WebJobs;
using Microsoft.Azure.WebJobs.Extensions.DurableTask;
using Microsoft.Azure.WebJobs.Extensions.Http;
using Microsoft.Extensions.Logging;

using Newtonsoft.Json;

namespace KeyVault.Acmebot
{
public class AddCertificateFunctions
{
[FunctionName(nameof(AddCertificate_HttpStart))]
public async Task<HttpResponseMessage> AddCertificate_HttpStart(
[HttpTrigger(AuthorizationLevel.Anonymous, "post", Route = "add-certificate")] HttpRequestMessage req,
[OrchestrationClient] DurableOrchestrationClient starter,
public async Task<IActionResult> AddCertificate_HttpStart(
[HttpTrigger(AuthorizationLevel.Anonymous, "post", Route = "add-certificate")] HttpRequest req,
[DurableClient] IDurableClient starter,
ILogger log)
{
if (!req.Headers.Contains("X-MS-CLIENT-PRINCIPAL-ID"))
if (!req.HttpContext.User.Identity.IsAuthenticated)
{
return req.CreateErrorResponse(HttpStatusCode.Unauthorized, $"Need to activate EasyAuth.");
return new UnauthorizedObjectResult("Need to activate EasyAuth.");
}

var request = await req.Content.ReadAsAsync<AddCertificateRequest>();
var request = JsonConvert.DeserializeObject<AddCertificateRequest>(await req.ReadAsStringAsync());

if (request?.Domains == null || request.Domains.Length == 0)
{
return req.CreateErrorResponse(HttpStatusCode.BadRequest, $"{nameof(request.Domains)} is empty.");
return new BadRequestObjectResult($"{nameof(request.Domains)} is empty.");
}

// Function input comes from the request content.
Expand Down
3 changes: 2 additions & 1 deletion KeyVault.Acmebot/Contracts/ISharedFunctions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,12 @@

using ACMESharp.Protocol;

using DurableTask.TypedProxy;

using KeyVault.Acmebot.Models;

using Microsoft.Azure.KeyVault.Models;
using Microsoft.Azure.Management.Dns.Models;
using Microsoft.Azure.WebJobs;

namespace KeyVault.Acmebot.Contracts
{
Expand Down
19 changes: 11 additions & 8 deletions KeyVault.Acmebot/GetDnsZonesFunctions.cs
Original file line number Diff line number Diff line change
@@ -1,13 +1,16 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Threading.Tasks;

using DurableTask.TypedProxy;

using KeyVault.Acmebot.Contracts;

using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Azure.WebJobs;
using Microsoft.Azure.WebJobs.Extensions.DurableTask;
using Microsoft.Azure.WebJobs.Extensions.Http;
using Microsoft.Extensions.Logging;

Expand All @@ -16,7 +19,7 @@ namespace KeyVault.Acmebot
public class GetDnsZonesFunctions
{
[FunctionName(nameof(GetDnsZones))]
public async Task<IList<string>> GetDnsZones([OrchestrationTrigger] DurableOrchestrationContext context)
public async Task<IList<string>> GetDnsZones([OrchestrationTrigger] IDurableOrchestrationContext context)
{
var activity = context.CreateActivityProxy<ISharedFunctions>();

Expand All @@ -26,14 +29,14 @@ public async Task<IList<string>> GetDnsZones([OrchestrationTrigger] DurableOrche
}

[FunctionName(nameof(GetDnsZones_HttpStart))]
public async Task<HttpResponseMessage> GetDnsZones_HttpStart(
[HttpTrigger(AuthorizationLevel.Anonymous, "get", Route = "get-dns-zones")] HttpRequestMessage req,
[OrchestrationClient] DurableOrchestrationClient starter,
public async Task<IActionResult> GetDnsZones_HttpStart(
[HttpTrigger(AuthorizationLevel.Anonymous, "get", Route = "get-dns-zones")] HttpRequest req,
[DurableClient] IDurableClient starter,
ILogger log)
{
if (!req.Headers.Contains("X-MS-CLIENT-PRINCIPAL-ID"))
if (!req.HttpContext.User.Identity.IsAuthenticated)
{
return req.CreateErrorResponse(HttpStatusCode.Unauthorized, $"Need to activate EasyAuth.");
return new UnauthorizedObjectResult("Need to activate EasyAuth.");
}

// Function input comes from the request content.
Expand Down
26 changes: 0 additions & 26 deletions KeyVault.Acmebot/Internal/Settings.cs

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,21 @@
using System.Threading.Tasks;

using Microsoft.Azure.WebJobs.Extensions.DurableTask;
using Microsoft.Extensions.Options;

namespace KeyVault.Acmebot.Internal
{
internal class InProcLifeCycleNotificationHelper : ILifeCycleNotificationHelper
internal class WebhookLifeCycleNotification : ILifeCycleNotificationHelper
{
public WebhookLifeCycleNotification(IHttpClientFactory httpClientFactory, IOptions<LetsEncryptOptions> options)
{
_httpClientFactory = httpClientFactory;
_options = options.Value;
}

private readonly IHttpClientFactory _httpClientFactory;
private readonly LetsEncryptOptions _options;

public Task OrchestratorStartingAsync(string hubName, string functionName, string instanceId, bool isReplay)
{
return Task.CompletedTask;
Expand All @@ -27,18 +37,16 @@ public Task OrchestratorTerminatedAsync(string hubName, string functionName, str
return Task.CompletedTask;
}

private static readonly HttpClient _httpClient = new HttpClient();

private static async Task PostEventAsync(string functionName, string instanceId, string reason)
private async Task PostEventAsync(string functionName, string instanceId, string reason)
{
if (string.IsNullOrEmpty(Settings.Default.Webhook))
if (string.IsNullOrEmpty(_options.Webhook))
{
return;
}

object model;

if (Settings.Default.Webhook.Contains("hooks.slack.com"))
if (_options.Webhook.Contains("hooks.slack.com"))
{
model = new
{
Expand All @@ -63,7 +71,9 @@ private static async Task PostEventAsync(string functionName, string instanceId,
};
}

await _httpClient.PostAsJsonAsync(Settings.Default.Webhook, model);
var httpClient = _httpClientFactory.CreateClient();

await httpClient.PostAsJsonAsync(_options.Webhook, model);
}
}
}
6 changes: 3 additions & 3 deletions KeyVault.Acmebot/KeyVault.Acmebot.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,14 @@
<AzureFunctionsVersion>v2</AzureFunctionsVersion>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="ACMESharpCore" Version="2.0.1.105" />
<PackageReference Include="ACMESharpCore" Version="2.1.0.113" />
<PackageReference Include="DnsClient" Version="1.2.0" />
<PackageReference Include="DurableTask.ActivityProxy" Version="1.0.1" />
<PackageReference Include="DurableTask.TypedProxy" Version="2.0.0" />
<PackageReference Include="Microsoft.Azure.Functions.Extensions" Version="1.0.0" />
<PackageReference Include="Microsoft.Azure.KeyVault" Version="3.0.4" />
<PackageReference Include="Microsoft.Azure.Management.Dns" Version="3.0.1" />
<PackageReference Include="Microsoft.Azure.Services.AppAuthentication" Version="1.3.1" />
<PackageReference Include="Microsoft.Azure.WebJobs.Extensions.DurableTask" Version="1.8.3" />
<PackageReference Include="Microsoft.Azure.WebJobs.Extensions.DurableTask" Version="2.0.0" />
<PackageReference Include="Microsoft.Extensions.Http" Version="2.2.0" />
<PackageReference Include="Microsoft.NET.Sdk.Functions" Version="1.0.29" />
</ItemGroup>
Expand Down
3 changes: 2 additions & 1 deletion KeyVault.Acmebot/PurgeInstanceHistoryFunctions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
using DurableTask.Core;

using Microsoft.Azure.WebJobs;
using Microsoft.Azure.WebJobs.Extensions.DurableTask;

namespace KeyVault.Acmebot
{
Expand All @@ -12,7 +13,7 @@ public class PurgeInstanceHistoryFunctions
[FunctionName(nameof(PurgeInstanceHistory_Timer))]
public Task PurgeInstanceHistory_Timer(
[TimerTrigger("0 0 6 * * 0")] TimerInfo timer,
[OrchestrationClient] DurableOrchestrationClient starter)
[DurableClient] IDurableClient starter)
{
return starter.PurgeInstanceHistoryAsync(
DateTime.MinValue,
Expand Down
10 changes: 8 additions & 2 deletions KeyVault.Acmebot/RenewCertificatesFunctions.cs
Original file line number Diff line number Diff line change
@@ -1,16 +1,19 @@
using System.Threading.Tasks;

using DurableTask.TypedProxy;

using KeyVault.Acmebot.Contracts;

using Microsoft.Azure.WebJobs;
using Microsoft.Azure.WebJobs.Extensions.DurableTask;
using Microsoft.Extensions.Logging;

namespace KeyVault.Acmebot
{
public class RenewCertificatesFunctions
{
[FunctionName(nameof(RenewCertificates))]
public async Task RenewCertificates([OrchestrationTrigger] DurableOrchestrationContext context, ILogger log)
public async Task RenewCertificates([OrchestrationTrigger] IDurableOrchestrationContext context, ILogger log)
{
var activity = context.CreateActivityProxy<ISharedFunctions>();

Expand All @@ -36,7 +39,10 @@ public async Task RenewCertificates([OrchestrationTrigger] DurableOrchestrationC
}

[FunctionName(nameof(RenewCertificates_Timer))]
public static async Task RenewCertificates_Timer([TimerTrigger("0 0 0 * * 1,3,5")] TimerInfo timer, [OrchestrationClient] DurableOrchestrationClient starter, ILogger log)
public static async Task RenewCertificates_Timer(
[TimerTrigger("0 0 0 * * 1,3,5")] TimerInfo timer,
[DurableClient] IDurableClient starter,
ILogger log)
{
// Function input comes from the request content.
var instanceId = await starter.StartNewAsync(nameof(RenewCertificates), null);
Expand Down
5 changes: 4 additions & 1 deletion KeyVault.Acmebot/SharedFunctions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@

using DnsClient;

using DurableTask.TypedProxy;

using KeyVault.Acmebot.Contracts;
using KeyVault.Acmebot.Internal;
using KeyVault.Acmebot.Models;
Expand All @@ -20,6 +22,7 @@
using Microsoft.Azure.Management.Dns;
using Microsoft.Azure.Management.Dns.Models;
using Microsoft.Azure.WebJobs;
using Microsoft.Azure.WebJobs.Extensions.DurableTask;
using Microsoft.Extensions.Options;

namespace KeyVault.Acmebot
Expand Down Expand Up @@ -48,7 +51,7 @@ public SharedFunctions(IHttpClientFactory httpClientFactory, LookupClient lookup
private readonly DnsManagementClient _dnsManagementClient;

[FunctionName(nameof(IssueCertificate))]
public async Task IssueCertificate([OrchestrationTrigger] DurableOrchestrationContext context)
public async Task IssueCertificate([OrchestrationTrigger] IDurableOrchestrationContext context)
{
var dnsNames = context.GetInput<string[]>();

Expand Down
4 changes: 3 additions & 1 deletion KeyVault.Acmebot/Startup.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
using Microsoft.Azure.KeyVault;
using Microsoft.Azure.Management.Dns;
using Microsoft.Azure.Services.AppAuthentication;
using Microsoft.Azure.WebJobs.Extensions.DurableTask;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Options;
Expand Down Expand Up @@ -34,7 +35,7 @@ public override void Configure(IFunctionsHostBuilder builder)

builder.Services.AddSingleton(new LookupClient { UseCache = false });

builder.Services.AddSingleton(provider =>
builder.Services.AddSingleton(provider =>
new KeyVaultClient(new KeyVaultClient.AuthenticationCallback(new AzureServiceTokenProvider().KeyVaultTokenCallback)));

builder.Services.AddSingleton(provider =>
Expand All @@ -48,6 +49,7 @@ public override void Configure(IFunctionsHostBuilder builder)
});

builder.Services.AddSingleton<IAcmeProtocolClientFactory, AcmeProtocolClientFactory>();
builder.Services.AddSingleton<ILifeCycleNotificationHelper, WebhookLifeCycleNotification>();

builder.Services.Configure<LetsEncryptOptions>(Configuration.GetSection("LetsEncrypt"));
}
Expand Down
4 changes: 2 additions & 2 deletions KeyVault.Acmebot/host.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@
"version": "2.0",
"extensions": {
"durableTask": {
"hubName": "DurableFunctionsHub",
"extendedSessionsEnabled": true,
"extendedSessionIdleTimeoutInSeconds": 60,
"CustomLifeCycleNotificationHelperType": "AzureKeyVault.LetsEncrypt.Internal.InProcLifeCycleNotificationHelper, AzureKeyVault.LetsEncrypt"
"extendedSessionIdleTimeoutInSeconds": 60
}
}
}

0 comments on commit 4a6b97e

Please sign in to comment.