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

Add a workflow for invoking bindings #123

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
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
91 changes: 91 additions & 0 deletions .github/workflows/binding-workflow-build.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
# ------------------------------------------------------------
# Copyright (c) Microsoft Corporation.
# Licensed under the MIT License.
# ------------------------------------------------------------

name: build-binding-workflow

on:
push:
branches:
- master
paths:
- 'binding-workflow/**'
- '.github/workflows/**'
pull_request:
branches:
- master
paths:
- 'binding-workflow/**'
- '.github/workflows/**'

jobs:
build:
name: build binding-workflow
runs-on: ubuntu-latest
env:
APP_REGISTRY: dapriotest
APP_IMAGE_NAME: binding-workflow
# TODO: APP_VER needs to be versioned correctly
APP_VER: dev
APP_DIR: ./binding-workflow
ARTIFACT_DIR: ./deploy_artifact
steps:
- name: Check out code
uses: actions/checkout@v2
- name: docker login
if: github.event_name != 'pull_request'
run: |
docker login -u ${{ secrets.DOCKER_REGISTRY_ID }} -p ${{ secrets.DOCKER_REGISTRY_PASS }}
- name: Build binding-workflow docker image
run: |
docker-compose build ${{ env.APP_IMAGE_NAME }}
docker tag ${{ env.APP_IMAGE_NAME }} ${{ env.APP_REGISTRY }}/${{ env.APP_IMAGE_NAME }}:${{ env.APP_VER }}
- name: Push binding-workflow image to dockerhub
if: github.event_name != 'pull_request'
run: |
docker push ${{ env.APP_REGISTRY }}/${{ env.APP_IMAGE_NAME }}:${{ env.APP_VER }}
- name: Copy deployment yaml to archive
run: |
mkdir -p ${{ env.ARTIFACT_DIR }}
cp ./longhaul-test/*.yml ${{ env.ARTIFACT_DIR }}
- name: Upload artifacts
uses: actions/upload-artifact@master
with:
name: longhaul-test
path: ${{ env.ARTIFACT_DIR }}
deploy:
name: deploy binding-workflow to test cluster
needs: build
if: github.event_name != 'pull_request'
runs-on: ubuntu-latest
env:
APP_NAMESPACE: longhaul-test
TEST_CLUSTER_NAME: dapr-seattle
TEST_RESOURCE_GROUP: dapr-test
ARTIFACT_DIR: ./deploy_artifact
steps:
- name: download artifacts
uses: actions/download-artifact@master
with:
name: longhaul-test
path: ${{ env.ARTIFACT_DIR }}
- name: Login Azure
run: |
az login --service-principal -u ${{ secrets.AZURE_LOGIN_USER }} -p ${{ secrets.AZURE_LOGIN_PASS }} --tenant ${{ secrets.AZURE_TENANT }} --output none
- name: Set up kubeconf for longhaul test environment
run: |
az aks get-credentials -n ${{ env.TEST_CLUSTER_NAME }} -g ${{ env.TEST_RESOURCE_GROUP }}
- name: Set up azure keyvault certificate secret
run: |
az keyvault secret download --vault-name longhaul-kv --name longhaul-cert --encoding base64 --file longhaul-cert.pfx
kubectl delete secret longhaulcert -n longhaul-test --ignore-not-found
kubectl create secret generic longhaulcert -n longhaul-test --from-file=longhaulcert=./longhaul-cert.pfx
- name: Deploy apps to longhaul test environment
run: |
kubectl apply -n ${{ env.APP_NAMESPACE }} -f ${{ env.ARTIFACT_DIR }}/secret-access-role.yml
kubectl apply -n ${{ env.APP_NAMESPACE }} -f ${{ env.ARTIFACT_DIR }}/secret-access-role-binding.yml
kubectl apply -n ${{ env.APP_NAMESPACE }} -f ${{ env.ARTIFACT_DIR }}/azure-keyvault.yml
kubectl apply -n ${{ env.APP_NAMESPACE }} -f ${{ env.ARTIFACT_DIR }}/azure-service-bus-binding.yml
kubectl apply -n ${{ env.APP_NAMESPACE }} -f ${{ env.ARTIFACT_DIR }}/azure-blob-storage-binding.yml
kubectl apply -n ${{ env.APP_NAMESPACE }} -f ${{ env.ARTIFACT_DIR }}/binding-workflow-deploy.yml & kubectl rollout restart -n ${{ env.APP_NAMESPACE }} deploy/binding-workflow-app
6 changes: 6 additions & 0 deletions all.sln
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ Project("{E53339B2-1760-4266-BCC7-CA923CBCF16C}") = "docker-compose", "docker-co
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "pubsub-workflow", "pubsub-workflow\pubsub-workflow.csproj", "{571AD477-1187-4E27-9ADB-CDD6E7370E8C}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "binding-workflow", "binding-workflow\binding-workflow.csproj", "{F4B8E286-57E3-4750-849F-A49F62C1AA4C}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand Down Expand Up @@ -63,6 +65,10 @@ Global
{571AD477-1187-4E27-9ADB-CDD6E7370E8C}.Debug|Any CPU.Build.0 = Debug|Any CPU
{571AD477-1187-4E27-9ADB-CDD6E7370E8C}.Release|Any CPU.ActiveCfg = Release|Any CPU
{571AD477-1187-4E27-9ADB-CDD6E7370E8C}.Release|Any CPU.Build.0 = Release|Any CPU
{F4B8E286-57E3-4750-849F-A49F62C1AA4C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{F4B8E286-57E3-4750-849F-A49F62C1AA4C}.Debug|Any CPU.Build.0 = Debug|Any CPU
{F4B8E286-57E3-4750-849F-A49F62C1AA4C}.Release|Any CPU.ActiveCfg = Release|Any CPU
{F4B8E286-57E3-4750-849F-A49F62C1AA4C}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand Down
37 changes: 37 additions & 0 deletions binding-workflow/Controllers/BindingsController.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
// ------------------------------------------------------------
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
// ------------------------------------------------------------

using Dapr.Client;
using Dapr.Tests.Common.Models;
using Microsoft.AspNetCore.Mvc;
using System;
using System.Collections.Generic;
using System.Threading.Tasks;

namespace BindingWorkflow
{
[ApiController]
public class BindingsController : ControllerBase
{
/// <summary>
/// Handle a message from the Azure Service Bus input binding.
/// </summary>
[HttpPost("/longhaul-invoke-binding")]
public async Task<IActionResult> HandleBinding([FromBody] BindingInvocationMessage message, [FromServices] DaprClient client)
{
Console.WriteLine($"Invoking binding {message.TargetBinding} with operation \"{message.TargetOperation}\" {message.InvocationCount} times.");
for (var i = 0; i < message.InvocationCount; i++)
{
var data = new Dictionary<string, string>(message.Data);
if (message.Metadata.ContainsKey("autoGenId")) {
data.Add("id", Guid.NewGuid().ToString());
}
await client.InvokeBindingAsync(message.TargetBinding, message.TargetOperation, data);
}
Console.WriteLine("Finished invoking binding.");
return Ok();
}
}
}
20 changes: 20 additions & 0 deletions binding-workflow/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# ------------------------------------------------------------
# Copyright (c) Microsoft Corporation.
# Licensed under the MIT License.
# ------------------------------------------------------------

FROM mcr.microsoft.com/dotnet/core/aspnet:3.1 AS base
WORKDIR /app
EXPOSE 3000 9988

FROM mcr.microsoft.com/dotnet/core/sdk:3.1 AS build-env
WORKDIR /app

COPY . ./
RUN dotnet restore binding-workflow/*.csproj
RUN dotnet publish binding-workflow/*.csproj -c Release -o /out

FROM base AS final
WORKDIR /app
COPY --from=build-env /out ./
ENTRYPOINT ["dotnet", "binding-workflow.dll"]
92 changes: 92 additions & 0 deletions binding-workflow/Program.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
// ------------------------------------------------------------
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
// ------------------------------------------------------------

using System;
using System.Collections.Generic;
using System.IO;
using System.Threading;
using Dapr.Client;
using Dapr.Tests.Common.Models;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using Prometheus;

namespace BindingWorkflow
{
public class Program
{
private static readonly string AzureServiceBusBinding = "longhaul-invoke-binding";
private static readonly string BlobStorageBinding = "longhaul-blob-binding";
private static readonly string CosmosDBBinding = "longhaul-cosmosdb-binding";
private static readonly string CreateOperation = "create";

public static void Main(string[] args)
{
Console.WriteLine("Starting bindings workflow.");

var server = new MetricServer(port: 9988);
server.Start();

var host = CreateHostBuilder(args).Build();

// Invoke the blob storage output binding 200 times every 5 minutes (2400 messages per hour).
var blobPublishTimer = StartInvokingBinding(300, BlobStorageBinding, CreateOperation, 200, new Dictionary<string, string>());
var cosmosDBPublishTimer = StartInvokingBinding(300, CosmosDBBinding, CreateOperation, 200, new Dictionary<string, string>() {
{ "autoGenId", "true"}
});

host.Run();

Console.WriteLine("Exiting bindings workflow.");

blobPublishTimer.Dispose();
cosmosDBPublishTimer.Dispose();
}

public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureLogging((hostingContext, config) =>
{
config.ClearProviders();
config.AddConsole();

})
.ConfigureWebHostDefaults(webBuilder =>
{
var appSettings = new ConfigurationBuilder()
.SetBasePath(Directory.GetCurrentDirectory())
.AddJsonFile($"appsettings.json", optional: true, reloadOnChange: true)
.AddCommandLine(args)
.Build();

webBuilder.UseStartup<Startup>()
.UseUrls(urls: $"http://*:{appSettings["DaprHTTPAppPort"]}");
});

static internal Timer StartInvokingBinding(int periodInSeconds, string targetBinding, string targetOperation, int invocationCount, Dictionary<string, string> metadata)
{
var client = new DaprClientBuilder().Build();

return new Timer(async (state) =>
{
Console.WriteLine($"Invoking binding to trigger {targetBinding} binding.");
var data = new Dictionary<string, string>();
data.Add("timestamp", DateTime.Now.ToLongTimeString());
data.Add("pk", Guid.NewGuid().ToString());
var request = new BindingInvocationMessage
{
TargetBinding = targetBinding,
TargetOperation = targetOperation,
InvocationCount = invocationCount,
Data = data,
Metadata = metadata,
};
await client.InvokeBindingAsync(AzureServiceBusBinding, CreateOperation, request);
}, null, TimeSpan.FromSeconds(new Random().Next(5, 10)), TimeSpan.FromSeconds(periodInSeconds));
}
}
}
28 changes: 28 additions & 0 deletions binding-workflow/Properties/launchSettings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
{
"iisSettings": {
"windowsAuthentication": false,
"anonymousAuthentication": true,
"iisExpress": {
"applicationUrl": "http://localhost:19822",
"sslPort": 44364
}
},
"profiles": {
"IIS Express": {
"commandName": "IISExpress",
"launchBrowser": true,
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
},
"storage_binding": {
"commandName": "Project",
"dotnetRunMessages": "true",
"launchBrowser": true,
"applicationUrl": "https://localhost:5001;http://localhost:5000",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
}
}
}
46 changes: 46 additions & 0 deletions binding-workflow/Startup.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
// ------------------------------------------------------------
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
// ------------------------------------------------------------

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;

namespace BindingWorkflow
{
public class Startup
{
// This method gets called by the runtime. Use this method to add services to the container.
// For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940
public void ConfigureServices(IServiceCollection services)
{
services.AddDaprClient();
services.AddControllers();
}

// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}

app.UseRouting();

app.UseCloudEvents();

app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
}
}
}
9 changes: 9 additions & 0 deletions binding-workflow/appsettings.Development.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft": "Warning",
"Microsoft.Hosting.Lifetime": "Information"
}
}
}
11 changes: 11 additions & 0 deletions binding-workflow/appsettings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft": "Warning",
"Microsoft.Hosting.Lifetime": "Information"
}
},
"AllowedHosts": "*",
"DaprHTTPAppPort": "3000"
}
17 changes: 17 additions & 0 deletions binding-workflow/binding-workflow.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<Project Sdk="Microsoft.NET.Sdk.Web">

<PropertyGroup>
<TargetFramework>netcoreapp3.1</TargetFramework>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Dapr.AspNetcore" Version="1.5.0" />
<PackageReference Include="Dapr.Client" Version="1.5.0" />
<PackageReference Include="prometheus-net" Version="5.0.1" />
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\common\common.csproj" />
</ItemGroup>

</Project>
Loading