From 7b76334e0c2e0d0f77975e53bef17e0c26367095 Mon Sep 17 00:00:00 2001 From: chgl Date: Wed, 23 Nov 2022 16:47:55 +0100 Subject: [PATCH 1/3] chore(deps): updated all deps --- src/Vfps/Vfps.csproj | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/Vfps/Vfps.csproj b/src/Vfps/Vfps.csproj index 30fd5aa..57e280a 100644 --- a/src/Vfps/Vfps.csproj +++ b/src/Vfps/Vfps.csproj @@ -7,9 +7,9 @@ - - - + + + @@ -18,9 +18,9 @@ runtime; build; native; contentfiles; analyzers; buildtransitive - - - + + + From 119143c1f4e99500c121552dd263a7f7396d9e10 Mon Sep 17 00:00:00 2001 From: chgl Date: Wed, 23 Nov 2022 18:17:25 +0100 Subject: [PATCH 2/3] refactor: move common properties to shared Directory.Build.props --- src/Directory.Build.props | 21 +++++++++++++++++++ src/Vfps.Benchmarks/Vfps.Benchmarks.csproj | 3 --- .../Vfps.IntegrationTests.csproj | 3 --- src/Vfps.LoadTests/Vfps.LoadTests.csproj | 16 +++++++++----- src/Vfps.Tests/Vfps.Tests.csproj | 3 --- src/Vfps/Vfps.csproj | 5 +---- 6 files changed, 33 insertions(+), 18 deletions(-) create mode 100644 src/Directory.Build.props diff --git a/src/Directory.Build.props b/src/Directory.Build.props new file mode 100644 index 0000000..d95f8ef --- /dev/null +++ b/src/Directory.Build.props @@ -0,0 +1,21 @@ + + + net7.0 + 11.0 + enable + enable + latest + true + + 1.1.0 + miracum.org + A very fast and resource-efficient pseudonym service. + © miracum.org. All rights reserved. + en-US + miracum.org + + + + true + + diff --git a/src/Vfps.Benchmarks/Vfps.Benchmarks.csproj b/src/Vfps.Benchmarks/Vfps.Benchmarks.csproj index 4ff04c0..19a77eb 100644 --- a/src/Vfps.Benchmarks/Vfps.Benchmarks.csproj +++ b/src/Vfps.Benchmarks/Vfps.Benchmarks.csproj @@ -2,9 +2,6 @@ Exe - net7.0 - enable - enable false diff --git a/src/Vfps.IntegrationTests/Vfps.IntegrationTests.csproj b/src/Vfps.IntegrationTests/Vfps.IntegrationTests.csproj index 66f8be1..01f519b 100644 --- a/src/Vfps.IntegrationTests/Vfps.IntegrationTests.csproj +++ b/src/Vfps.IntegrationTests/Vfps.IntegrationTests.csproj @@ -1,9 +1,6 @@ - net7.0 - enable - enable false diff --git a/src/Vfps.LoadTests/Vfps.LoadTests.csproj b/src/Vfps.LoadTests/Vfps.LoadTests.csproj index ec1a52e..cd537b6 100644 --- a/src/Vfps.LoadTests/Vfps.LoadTests.csproj +++ b/src/Vfps.LoadTests/Vfps.LoadTests.csproj @@ -1,15 +1,21 @@ - Exe - net7.0 - enable - enable - + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + + diff --git a/src/Vfps.Tests/Vfps.Tests.csproj b/src/Vfps.Tests/Vfps.Tests.csproj index 5edc155..7ee3245 100644 --- a/src/Vfps.Tests/Vfps.Tests.csproj +++ b/src/Vfps.Tests/Vfps.Tests.csproj @@ -1,9 +1,6 @@ - net7.0 - enable - enable false diff --git a/src/Vfps/Vfps.csproj b/src/Vfps/Vfps.csproj index 57e280a..92cbeef 100644 --- a/src/Vfps/Vfps.csproj +++ b/src/Vfps/Vfps.csproj @@ -1,8 +1,5 @@ - net7.0 - enable - enable true @@ -32,6 +29,6 @@ - + From 06d6abb829481d25f4820bc6ba90129b3537b3ce Mon Sep 17 00:00:00 2001 From: chgl Date: Wed, 23 Nov 2022 21:44:16 +0100 Subject: [PATCH 3/3] ci: added nightly-running chaos test supported by NBomber stress-test --- .checkov.yml | 3 + .dockerignore | 2 + .github/workflows/nightly-chaos.yaml | 80 +++++++++++++++++ .github/workflows/release-please.yaml | 3 +- .gitignore | 3 + Dockerfile | 31 ++++++- src/Vfps.LoadTests/Program.cs | 108 ++++++++++++++++------- src/Vfps.LoadTests/Vfps.LoadTests.csproj | 8 -- tests/chaos/argo-workflow.yaml | 74 ++++++++++++++++ tests/chaos/argo-workflows-values.yaml | 8 ++ tests/chaos/chaos-mesh-rbac.yaml | 39 ++++++++ tests/chaos/chaos.yaml | 21 +++++ tests/chaos/vfps-values.yaml | 1 + 13 files changed, 336 insertions(+), 45 deletions(-) create mode 100644 .checkov.yml create mode 100644 .github/workflows/nightly-chaos.yaml create mode 100644 tests/chaos/argo-workflow.yaml create mode 100644 tests/chaos/argo-workflows-values.yaml create mode 100644 tests/chaos/chaos-mesh-rbac.yaml create mode 100644 tests/chaos/chaos.yaml create mode 100644 tests/chaos/vfps-values.yaml diff --git a/.checkov.yml b/.checkov.yml new file mode 100644 index 0000000..04ca71b --- /dev/null +++ b/.checkov.yml @@ -0,0 +1,3 @@ +skip-check: + - CKV_ARGO_2 + - CKV_DOCKER_2 diff --git a/.dockerignore b/.dockerignore index 6c057ab..598f543 100644 --- a/.dockerignore +++ b/.dockerignore @@ -2,5 +2,7 @@ !src !.editorconfig !*.sln +!Directory.Build.props +!tests/chaos src/**/bin src/**/obj diff --git a/.github/workflows/nightly-chaos.yaml b/.github/workflows/nightly-chaos.yaml new file mode 100644 index 0000000..72e724e --- /dev/null +++ b/.github/workflows/nightly-chaos.yaml @@ -0,0 +1,80 @@ +name: nightly chaos testing + +on: + schedule: + # daily at 04:07. + - cron: "07 04 * * *" + +# Declare default permissions as read only. +permissions: read-all + +jobs: + chaos-testing: + name: chaos testing + runs-on: ubuntu-22.04 + steps: + - name: Checkout + uses: actions/checkout@2541b1294d2704b0964813337f33b291d3f8596b # tag=v3 + with: + fetch-depth: 0 + + - name: Build stress testing image + id: build-image + uses: docker/build-push-action@c84f38281176d4c9cdb1626ffafcd6b3911b5d94 # tag=v3 + with: + push: false + load: true + tags: ghcr.io/miracum/vfps/stress-test:v1 + cache-from: type=gha + cache-to: type=gha,mode=max + target: stress-test + + - name: Create KinD cluster + uses: helm/kind-action@9e8295d178de23cbfbd8fa16cf844eec1d773a07 # tag=v1.4.0 + with: + cluster_name: kind + + - name: Load stress-test image into KinD + run: | + kind load docker-image ghcr.io/miracum/vfps/stress-test:v1 + + - name: Install prerequisites + working-directory: tests/chaos + run: | + curl -sL -o - https://github.com/argoproj/argo-workflows/releases/download/v3.4.3/argo-linux-amd64.gz | gunzip > argo + + kubectl create ns vfps + + helm repo add chaos-mesh https://charts.chaos-mesh.org + helm upgrade --install chaos-mesh chaos-mesh/chaos-mesh \ + --create-namespace \ + --wait \ + -n chaos-mesh \ + --set chaosDaemon.runtime=containerd \ + --set chaosDaemon.socketPath='/run/containerd/containerd.sock' \ + --version 2.4.3 + + kubectl apply -f chaos-mesh-rbac.yaml + + helm repo add argo https://argoproj.github.io/argo-helm + helm upgrade --install argo-workflows argo/argo-workflows \ + --create-namespace \ + --wait \ + -n argo-workflows \ + -f argo-workflows-values.yaml + + - name: Install vfps + working-directory: tests/chaos + run: | + helm repo add miracum https://miracum.github.io/charts + helm upgrade --install \ + -n vfps \ + -f vfps-values.yaml \ + --wait \ + --version=^1.0.0 \ + vfps miracum/vfps + + - name: Run chaos testing workflow + working-directory: tests/chaos + run: | + ./argo submit tests/chaos/argo-workflow.yaml -n vfps --wait diff --git a/.github/workflows/release-please.yaml b/.github/workflows/release-please.yaml index ce5a52a..f227020 100644 --- a/.github/workflows/release-please.yaml +++ b/.github/workflows/release-please.yaml @@ -19,7 +19,8 @@ jobs: with: token: ${{ secrets.RELEASE_PLEASE_GITHUB_TOKEN }} release-type: simple - package-name: release-please-action + extra-files: | + src/Directory.Build.props changelog-types: | [ { "type": "feat", "section": "Features" }, diff --git a/.gitignore b/.gitignore index 47875c5..ae48773 100644 --- a/.gitignore +++ b/.gitignore @@ -405,3 +405,6 @@ coverage/ coveragereport/ megalinter-reports/ + +# used by NBomber +reports/ diff --git a/Dockerfile b/Dockerfile index 12c4814..dbf533d 100644 --- a/Dockerfile +++ b/Dockerfile @@ -14,9 +14,10 @@ WORKDIR /build ENV DOTNET_CLI_TELEMETRY_OPTOUT=1 \ PATH="/root/.dotnet/tools:${PATH}" -RUN dotnet tool install --global dotnet-ef +RUN dotnet tool install --global dotnet-ef --version=7.0.0 -COPY src/Vfps/Vfps.csproj src/Vfps/Vfps.csproj +COPY src/Directory.Build.props src/ +COPY src/Vfps/Vfps.csproj src/Vfps/ RUN dotnet restore --runtime=linux-x64 src/Vfps/Vfps.csproj @@ -37,7 +38,6 @@ dotnet ef migrations bundle \ --project=src/Vfps/Vfps.csproj \ --startup-project=src/Vfps/Vfps.csproj \ --configuration=Release \ - --target-runtime=linux-x64 \ --verbose \ -o /build/efbundle EOF @@ -51,6 +51,31 @@ RUN dotnet test \ -l "console;verbosity=detailed" \ --settings=runsettings.xml +FROM build AS build-stress-test +WORKDIR /build/src/Vfps.LoadTests +RUN < - { - var request = Http.CreateRequest("POST", baseUrl + "/namespaces") - .WithHeader("Accept", "application/json") - .WithBody(JsonContent.Create(new - { - Name = "load-test", - PseudonymLength = 32, - PseudonymGenerationMethod = 1, - })); - - return Http.Send(request, context); - }); +using var channel = GrpcChannel.ForAddress(grpcAddress, new GrpcChannelOptions() +{ + ServiceConfig = new ServiceConfig() + { + MethodConfigs = { defaultMethodConfig } + }, + Credentials = ChannelCredentials.Insecure, + UnsafeUseInsecureChannelCallCredentials = true, +}); + +var namespaceClient = new NamespaceService.NamespaceServiceClient(channel); +var pseudonymClient = new PseudonymService.PseudonymServiceClient(channel); + +var namespaceRequest = new NamespaceServiceCreateRequest() +{ + Name = "stress-test", + PseudonymGenerationMethod = PseudonymGenerationMethod.SecureRandomBase64UrlEncoded, + PseudonymLength = 16, + PseudonymPrefix = "stress-", +}; var createPseudonyms = Step.Create("create_pseudonyms", - clientFactory: httpFactory, - execute: context => + execute: async context => { - var request = Http.CreateRequest("POST", baseUrl + "/namespaces/load-test/pseudonyms") - .WithHeader("Accept", "application/json") - .WithBody(JsonContent.Create(new - { - OriginalValue = Guid.NewGuid().ToString(), - })); - - return Http.Send(request, context); + var request = new PseudonymServiceCreateRequest() + { + Namespace = namespaceRequest.Name, + OriginalValue = Guid.NewGuid().ToString(), + }; + + try + { + var response = await pseudonymClient.CreateAsync(request); + return Response.Ok(statusCode: 200, sizeBytes: request.CalculateSize() + response.CalculateSize()); + } + catch (RpcException exc) + { + context.Logger.Error(exc, "Pseudonym creation failed"); + return Response.Fail(); + } }); var scenario = ScenarioBuilder - .CreateScenario("create_namespace_and_pseudonyms", createNamespace, createPseudonyms) + .CreateScenario("stress_pseudonym_creation", createPseudonyms) + .WithInit(async context => + { + try + { + var response = await namespaceClient.CreateAsync(namespaceRequest); + } + catch (RpcException exc) when (exc.StatusCode == StatusCode.AlreadyExists) + { + context.Logger.Warning($"Namespace {namespaceRequest.Name} already exists. Continuing anyway."); + } + }) .WithWarmUpDuration(TimeSpan.FromSeconds(5)) .WithLoadSimulations( - Simulation.InjectPerSec(rate: 100, during: TimeSpan.FromSeconds(30)) + Simulation.RampConstant(copies: 10, during: TimeSpan.FromMinutes(4)), + Simulation.KeepConstant(copies: 100, during: TimeSpan.FromMinutes(4)), + Simulation.InjectPerSecRandom(minRate: 10, maxRate: 50, during: TimeSpan.FromMinutes(4)) ); // creates ping plugin that brings additional reporting data -var pingPluginConfig = PingPluginConfig.CreateDefault(new[] { "127.0.0.1" }); +var pingPluginConfig = PingPluginConfig.CreateDefault(new[] { grpcAddress.Host }); var pingPlugin = new PingPlugin(pingPluginConfig); -NBomberRunner +var stats = NBomberRunner .RegisterScenarios(scenario) .WithWorkerPlugins(pingPlugin) .Run(); + +Debug.Assert(stats.FailCount < 100); diff --git a/src/Vfps.LoadTests/Vfps.LoadTests.csproj b/src/Vfps.LoadTests/Vfps.LoadTests.csproj index cd537b6..bd7e712 100644 --- a/src/Vfps.LoadTests/Vfps.LoadTests.csproj +++ b/src/Vfps.LoadTests/Vfps.LoadTests.csproj @@ -4,14 +4,6 @@ - - - - - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - diff --git a/tests/chaos/argo-workflow.yaml b/tests/chaos/argo-workflow.yaml new file mode 100644 index 0000000..c924394 --- /dev/null +++ b/tests/chaos/argo-workflow.yaml @@ -0,0 +1,74 @@ +# yaml-language-server: $schema=https://raw.githubusercontent.com/argoproj/argo-workflows/v3.4.3/api/jsonschema/schema.json +apiVersion: argoproj.io/v1alpha1 +kind: Workflow +metadata: + generateName: vfps-chaos-workflow- +spec: + entrypoint: run-chaos-and-test + serviceAccountName: chaos-mesh-cluster-manager + templates: + - name: test + container: + image: ghcr.io/miracum/vfps/stress-test:v1 + imagePullPolicy: IfNotPresent + command: + - dotnet + args: + - /opt/vfps-stress/Vfps.LoadTests.dll + env: + - name: VFPS_GRPC_ADDRESS + value: dns:///vfps-headless:8081 + securityContext: + allowPrivilegeEscalation: false + capabilities: + drop: + - ALL + privileged: false + runAsNonRoot: true + + - name: install-chaos + container: + image: ghcr.io/miracum/vfps/stress-test:v1 + imagePullPolicy: IfNotPresent + command: + - kubectl + args: + - apply + - -f + - /tmp/chaos.yaml + securityContext: + allowPrivilegeEscalation: false + capabilities: + drop: + - ALL + privileged: false + runAsNonRoot: true + + - name: delete-chaos + container: + image: ghcr.io/miracum/vfps/stress-test:v1 + imagePullPolicy: IfNotPresent + command: + - kubectl + args: + - delete + - -f + - /tmp/chaos.yaml + securityContext: + allowPrivilegeEscalation: false + capabilities: + drop: + - ALL + privileged: false + runAsNonRoot: true + + - name: run-chaos-and-test + dag: + tasks: + - name: test + template: test + - name: install-chaos + template: install-chaos + - name: delete-chaos + depends: "install-chaos && (test.Succeeded || test.Failed)" + template: delete-chaos diff --git a/tests/chaos/argo-workflows-values.yaml b/tests/chaos/argo-workflows-values.yaml new file mode 100644 index 0000000..d2b68d6 --- /dev/null +++ b/tests/chaos/argo-workflows-values.yaml @@ -0,0 +1,8 @@ +controller: + workflowNamespaces: + - default + - argo-workflows + - vfps + +server: + extraArgs: [--auth-mode=server] diff --git a/tests/chaos/chaos-mesh-rbac.yaml b/tests/chaos/chaos-mesh-rbac.yaml new file mode 100644 index 0000000..336ba42 --- /dev/null +++ b/tests/chaos/chaos-mesh-rbac.yaml @@ -0,0 +1,39 @@ +kind: ServiceAccount +apiVersion: v1 +metadata: + namespace: chaos-mesh + name: chaos-mesh-cluster-manager +--- +kind: ServiceAccount +apiVersion: v1 +metadata: + namespace: vfps + name: chaos-mesh-cluster-manager +--- +kind: ClusterRole +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: role-chaos-mesh-cluster-manager +rules: + - apiGroups: [""] + resources: ["pods", "namespaces"] + verbs: ["get", "watch", "list"] + - apiGroups: ["chaos-mesh.org"] + resources: ["*"] + verbs: ["get", "list", "watch", "create", "delete", "patch", "update"] +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: bind-chaos-mesh-cluster-manager +subjects: + - kind: ServiceAccount + name: chaos-mesh-cluster-manager + namespace: chaos-mesh + - kind: ServiceAccount + name: chaos-mesh-cluster-manager + namespace: vfps +roleRef: + kind: ClusterRole + name: role-chaos-mesh-cluster-manager + apiGroup: rbac.authorization.k8s.io diff --git a/tests/chaos/chaos.yaml b/tests/chaos/chaos.yaml new file mode 100644 index 0000000..783f93e --- /dev/null +++ b/tests/chaos/chaos.yaml @@ -0,0 +1,21 @@ +apiVersion: chaos-mesh.org/v1alpha1 +kind: Schedule +metadata: + namespace: vfps + name: fail-one-of-the-vfps-pods +spec: + schedule: "@every 1m" + concurrencyPolicy: Forbid + historyLimit: 1 + type: PodChaos + podChaos: + selector: + namespaces: + - vfps + labelSelectors: + app.kubernetes.io/name: vfps + app.kubernetes.io/instance: vfps + mode: one + action: pod-failure + duration: 30s +# TODO: could add database/cnpg chaos if deployed HA. diff --git a/tests/chaos/vfps-values.yaml b/tests/chaos/vfps-values.yaml new file mode 100644 index 0000000..6bc803e --- /dev/null +++ b/tests/chaos/vfps-values.yaml @@ -0,0 +1 @@ +replicaCount: 3