diff --git a/.github/workflows/chart.yaml b/.github/workflows/chart.yaml new file mode 100644 index 0000000..ec6e119 --- /dev/null +++ b/.github/workflows/chart.yaml @@ -0,0 +1,72 @@ +--- +name: Chart + +on: + push: + branches: [main] + pull_request: + branches: [main] + +jobs: + lint: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Set up Helm + uses: azure/setup-helm@v4 + with: + version: v3.12.0 + + # Python is required because `ct lint` runs Yamale (https://github.com/23andMe/Yamale) and + # yamllint (https://github.com/adrienverge/yamllint) which require Python + - name: Set up Python + uses: actions/setup-python@v5 + with: + python-version: 3.x + + - name: Set up chart-testing + uses: helm/chart-testing-action@v2 + + - name: Run chart-testing (lint) + run: ct lint --config ct.yaml + + test: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Set up Helm + uses: azure/setup-helm@v4 + with: + version: v3.12.0 + + - name: Set up chart-testing + uses: helm/chart-testing-action@v2 + + - name: Set up buildx + uses: docker/setup-buildx-action@v3 + + - name: Build scrubbed image + uses: docker/build-push-action@v6 + with: + context: ./ + load: true + tags: quay.io/${{ github.repository }}/scrubbed:latest + + - name: Create kind cluster + uses: helm/kind-action@v1 + + - name: Load dev images into k8s + run: kind load docker-image quay.io/${{ github.repository }}/scrubbed --name chart-testing + + - name: Install kube-prometheus stack CRDs + run: | + export KUBE_PROMETHEUS_STACK_VERSION=58.4.0 + kubectl apply -f https://raw.githubusercontent.com/prometheus-community/helm-charts/kube-prometheus-stack-$KUBE_PROMETHEUS_STACK_VERSION/charts/kube-prometheus-stack/charts/crds/crds/crd-servicemonitors.yaml + kubectl apply -f https://raw.githubusercontent.com/prometheus-community/helm-charts/kube-prometheus-stack-$KUBE_PROMETHEUS_STACK_VERSION/charts/kube-prometheus-stack/charts/crds/crds/crd-podmonitors.yaml + kubectl apply -f https://raw.githubusercontent.com/prometheus-community/helm-charts/kube-prometheus-stack-$KUBE_PROMETHEUS_STACK_VERSION/charts/kube-prometheus-stack/charts/crds/crds/crd-prometheusrules.yaml + + - name: Run chart-testing (install) + run: ct --config=ct.yaml install diff --git a/.gitignore b/.gitignore index 49a1392..d0b335b 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,2 @@ -scrubbed -coverage.coverprofile \ No newline at end of file +./scrubbed +coverage.coverprofile diff --git a/ct.yaml b/ct.yaml new file mode 100644 index 0000000..145cdf8 --- /dev/null +++ b/ct.yaml @@ -0,0 +1,3 @@ +target-branch: main +charts: + - deploy/charts/scrubbed diff --git a/deploy/charts/scrubbed/.helmignore b/deploy/charts/scrubbed/.helmignore new file mode 100644 index 0000000..0e8a0eb --- /dev/null +++ b/deploy/charts/scrubbed/.helmignore @@ -0,0 +1,23 @@ +# Patterns to ignore when building packages. +# This supports shell glob matching, relative path matching, and +# negation (prefixed with !). Only one pattern per line. +.DS_Store +# Common VCS dirs +.git/ +.gitignore +.bzr/ +.bzrignore +.hg/ +.hgignore +.svn/ +# Common backup files +*.swp +*.bak +*.tmp +*.orig +*~ +# Various IDEs +.project +.idea/ +*.tmproj +.vscode/ diff --git a/deploy/charts/scrubbed/Chart.yaml b/deploy/charts/scrubbed/Chart.yaml new file mode 100644 index 0000000..0ea9f40 --- /dev/null +++ b/deploy/charts/scrubbed/Chart.yaml @@ -0,0 +1,18 @@ +apiVersion: v2 +name: scrubbed +description: Deploy Scrubbed via Helm +type: application +version: 0.1.0 +appVersion: "v0.3.0" +keywords: + - scrubbed + - alertmanager + - webhook + - prometheus +home: https://github.com/adfinis/scrubbed +sources: + - https://github.com/adfinis/scrubbed/tree/main/deploy/charts/scrubbed +maintainers: + - name: adfinis + email: support@adfinis.com + url: https://adfinis.com diff --git a/deploy/charts/scrubbed/README.md b/deploy/charts/scrubbed/README.md new file mode 100644 index 0000000..ccb88de --- /dev/null +++ b/deploy/charts/scrubbed/README.md @@ -0,0 +1,51 @@ +# scrubbed + +![Version: 0.1.0](https://img.shields.io/badge/Version-0.1.0-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ![AppVersion: v0.3.0](https://img.shields.io/badge/AppVersion-v0.3.0-informational?style=flat-square) + +Deploy Scrubbed via Helm + +**Homepage:** + +## Maintainers + +| Name | Email | Url | +| ---- | ------ | --- | +| adfinis | | | + +## Source Code + +* + +## Values + +| Key | Type | Default | Description | +|-----|------|---------|-------------| +| image.repository | string | `"quay.io/adfinis/scrubbed"` | Scrubbed image repository | +| image.tag | string | `nil` | Scrubbed image version | +| replicaCount | int | `1` | Number of replicas | +| scrubbed.alertAnnotations | string | `""` | Space separated list of alert annotations to keep | +| scrubbed.alertLabels | string | `"alertname severity"` | Space separated list of alert labels to keep | +| scrubbed.commonAnnotations | string | `""` | Space separated list of common annotations to keep | +| scrubbed.commonLabels | string | `"alertname severity"` | Space separated list of common labels to keep | +| scrubbed.destinationURL | string | `"http://alert-receiver:8888/webhook"` | Destination URL to send scrubbed alerts to | +| scrubbed.groupLabels | string | `""` | Space separated list of group labels to keep | +| scrubbed.listenHost | string | `"0.0.0.0"` | Listener host of Scrubbed service | +| scrubbed.listenPort | string | `"8080"` | Listener port of Scrubbed service | +| scrubbed.logLevel | string | `"INFO"` | Scrubbed log level | +| scrubbed.resources | object | `{}` | Resource limits and requests for scrubbed | +| scrubbed.serviceName | string | `"scrubbed"` | Scrubbed service name | +| signalilo.alertmanagerPluginOutputAnnotations | string | `"description\nmessage\n"` | The name of an annotation to retrieve the plugin_output from | +| signalilo.debug | string | `"0"` | If true, enable debugging mode in Icinga client | +| signalilo.enabled | bool | `false` | Enable Signalilo sidecar. If enabled, use image scrubbed-signalilo. | +| signalilo.icingaCA | string | `""` | A PEM string of the trusted CA certificate for the Icinga2 API certificate | +| signalilo.icingaHostname | string | `""` | Name of the Servicehost in Icinga2 | +| signalilo.icingaURL | string | `""` | URL of the Icinga API. It's possible to specify one or more URLs. The Parameter content will be split on newline character | +| signalilo.icingaUUID | string | `"00000000-0000-0000-0000-000000000000"` | UUID which identifies the Signalilo instance. | +| signalilo.icingaUsername | string | `""` | Authentication against Icinga2 API. | +| signalilo.listenPort | string | `"8888"` | Listen port of Signalilo service | +| signalilo.resources | object | `{}` | Resource limits and requests for scrubbed | +| signalilo.serviceName | string | `"signalilo"` | Signalilo service name | +| signalilo.testSecret | bool | `false` | generate secret for CI testing, if false provide your own. Required keys are SIGNALILO_ALERTMANAGER_BEARER_TOKEN and SIGNALILO_ICINGA_PASSWORD | + +---------------------------------------------- +Autogenerated from chart metadata using [helm-docs v1.14.2](https://github.com/norwoodj/helm-docs/releases/v1.14.2) diff --git a/deploy/charts/scrubbed/ci/default-values.yaml b/deploy/charts/scrubbed/ci/default-values.yaml new file mode 100644 index 0000000..175189d --- /dev/null +++ b/deploy/charts/scrubbed/ci/default-values.yaml @@ -0,0 +1,5 @@ +image: + repository: quay.io/adfinis/scrubbed-signalilo + +scrubbed: + destinationURL: "http://signalilo:8888/webhook" diff --git a/deploy/charts/scrubbed/templates/_helpers.tpl b/deploy/charts/scrubbed/templates/_helpers.tpl new file mode 100644 index 0000000..f1ede7f --- /dev/null +++ b/deploy/charts/scrubbed/templates/_helpers.tpl @@ -0,0 +1,51 @@ +{{/* vim: set filetype=mustache: */}} +{{/* +Expand the name of the chart. +*/}} +{{- define "scrubbed.name" -}} +{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" -}} +{{- end -}} + +{{/* +Create a default fully qualified app name. +We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). +If release name contains chart name it will be used as a full name. +*/}} +{{- define "scrubbed.fullname" -}} +{{- if .Values.fullnameOverride -}} +{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" -}} +{{- else -}} +{{- $name := default .Chart.Name .Values.nameOverride -}} +{{- if contains $name .Release.Name -}} +{{- .Release.Name | trunc 63 | trimSuffix "-" -}} +{{- else -}} +{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" -}} +{{- end -}} +{{- end -}} +{{- end -}} + +{{/* +Create chart name and version as used by the chart label. +*/}} +{{- define "scrubbed.chart" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" -}} +{{- end -}} + +{{/* +Common labels +*/}} +{{- define "scrubbed.labels" -}} +helm.sh/chart: {{ .Chart.Name }}-{{ .Chart.Version | replace "+" "_" }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +app.kubernetes.io/part-of: {{ .Chart.Name }} +app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} +{{ include "scrubbed.selectorLabels" . }} +{{- end -}} + +{{/* +Selector labels +*/}} +{{- define "scrubbed.selectorLabels" -}} +app.kubernetes.io/name: {{ include "scrubbed.name" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +{{- end -}} diff --git a/deploy/charts/scrubbed/templates/configmap-scrubbed.yaml b/deploy/charts/scrubbed/templates/configmap-scrubbed.yaml new file mode 100644 index 0000000..949d628 --- /dev/null +++ b/deploy/charts/scrubbed/templates/configmap-scrubbed.yaml @@ -0,0 +1,17 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ include "scrubbed.fullname" . }} + labels: + {{- include "scrubbed.labels" . | nindent 4 }} + app.kubernetes.io/component: scrubbed +data: + SCRUBBED_ALERT_ANNOTATIONS: {{ .Values.scrubbed.alertAnnotations | quote }} + SCRUBBED_ALERT_LABELS: {{ .Values.scrubbed.alertLabels | quote }} + SCRUBBED_COMMON_ANNOTATIONS: {{ .Values.scrubbed.commonAnnotations | quote }} + SCRUBBED_COMMON_LABELS: {{ .Values.scrubbed.commonLabels | quote }} + SCRUBBED_GROUP_LABELS: {{ .Values.scrubbed.groupLabels | quote }} + SCRUBBED_DESTINATION_URL: {{ .Values.scrubbed.destinationURL | quote }} + SCRUBBED_LISTEN_PORT: {{ .Values.scrubbed.listenPort | quote }} + SCRUBBED_LISTEN_HOST: {{ .Values.scrubbed.listenHost | quote }} + SCRUBBED_LOG_LEVEL: {{ .Values.scrubbed.logLevel | quote }} diff --git a/deploy/charts/scrubbed/templates/configmap-signalilo.yaml b/deploy/charts/scrubbed/templates/configmap-signalilo.yaml new file mode 100644 index 0000000..2710a13 --- /dev/null +++ b/deploy/charts/scrubbed/templates/configmap-signalilo.yaml @@ -0,0 +1,18 @@ +{{- if .Values.signalilo.enabled -}} +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ include "scrubbed.fullname" . }}-signalilo + labels: + {{- include "scrubbed.labels" . | nindent 4 }} + app.kubernetes.io/component: signalilo +data: + SIGNALILO_ALERTMANAGER_PLUGINOUTPUT_ANNOTATIONS: {{ .Values.signalilo.alertmanagerPluginOutputAnnotations | quote }} + SIGNALILO_ALERTMANAGER_PORT: {{ .Values.signalilo.listenPort | quote }} + SIGNALILO_ICINGA_CA: {{ .Values.signalilo.icingaCA | quote }} + SIGNALILO_ICINGA_DEBUG: {{ .Values.signalilo.debug | quote }} + SIGNALILO_ICINGA_HOSTNAME: {{ .Values.signalilo.icingaHostname | quote }} + SIGNALILO_ICINGA_URL: {{ .Values.signalilo.icingaURL | quote }} + SIGNALILO_ICINGA_USERNAME: {{ .Values.signalilo.icingaUsername | quote }} + SIGNALILO_UUID: {{ .Values.signalilo.icingaUUID | quote }} +{{- end -}} diff --git a/deploy/charts/scrubbed/templates/deployment.yaml b/deploy/charts/scrubbed/templates/deployment.yaml new file mode 100644 index 0000000..312dbeb --- /dev/null +++ b/deploy/charts/scrubbed/templates/deployment.yaml @@ -0,0 +1,108 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + labels: + {{- include "scrubbed.labels" . | nindent 4 }} + app.kubernetes.io/component: scrubbed + name: {{ include "scrubbed.fullname" . }} +spec: + progressDeadlineSeconds: 60 + replicas: {{ .Values.replicaCount }} + revisionHistoryLimit: 2 + selector: + matchLabels: + {{- include "scrubbed.selectorLabels" . | nindent 6 }} + strategy: + rollingUpdate: + maxSurge: 25% + maxUnavailable: 25% + type: RollingUpdate + template: + metadata: + labels: + {{- include "scrubbed.labels" . | nindent 8 }} + app.kubernetes.io/component: scrubbed + spec: + containers: + - command: + - scrubbed + envFrom: + - configMapRef: + name: {{ include "scrubbed.fullname" . }} + image: "{{ .Values.image.repository }}:{{ default .Chart.AppVersion .Values.image.tag }}" + imagePullPolicy: IfNotPresent + livenessProbe: + failureThreshold: 3 + httpGet: + path: /healthz + port: {{ .Values.scrubbed.listenPort }} + scheme: HTTP + periodSeconds: 10 + successThreshold: 1 + timeoutSeconds: 1 + name: scrubbed + ports: + - containerPort: {{ .Values.scrubbed.listenPort }} + protocol: TCP + readinessProbe: + failureThreshold: 3 + httpGet: + path: /healthz + port: {{ .Values.scrubbed.listenPort }} + scheme: HTTP + periodSeconds: 10 + successThreshold: 1 + timeoutSeconds: 1 + resources: +{{ toYaml .Values.scrubbed.resources | indent 10 }} + terminationMessagePath: /dev/termination-log + terminationMessagePolicy: File +{{- if .Values.signalilo.enabled }} + - command: + - signalilo + envFrom: + - configMapRef: + name: {{ include "scrubbed.fullname" . }}-signalilo + - secretRef: + name: {{ include "scrubbed.fullname" . }}-signalilo + image: "{{ .Values.image.repository }}:{{ default .Chart.AppVersion .Values.image.tag }}" + imagePullPolicy: IfNotPresent + livenessProbe: + failureThreshold: 3 + httpGet: + path: /healthz + port: {{ .Values.signalilo.listenPort }} + scheme: HTTP + periodSeconds: 10 + successThreshold: 1 + timeoutSeconds: 1 + name: signalilo + ports: + - containerPort: {{ .Values.signalilo.listenPort }} + protocol: TCP + readinessProbe: + failureThreshold: 3 + httpGet: + path: /healthz + port: {{ .Values.signalilo.listenPort }} + scheme: HTTP + periodSeconds: 10 + successThreshold: 1 + timeoutSeconds: 1 + resources: +{{ toYaml .Values.scrubbed.resources | indent 10 }} + terminationMessagePath: /dev/termination-log + terminationMessagePolicy: File +{{- end }} + dnsPolicy: ClusterFirst + restartPolicy: Always + securityContext: {} + serviceAccountName: {{ include "scrubbed.fullname" . }} + terminationGracePeriodSeconds: 10 + tolerations: + - effect: NoSchedule + operator: Exists +{{- if .Values.scrubbed.nodeSelector }} + nodeSelector: +{{ toYaml .Values.scrubbed.nodeSelector | indent 8 }} +{{- end }} diff --git a/deploy/charts/scrubbed/templates/secret-signalilo.yaml b/deploy/charts/scrubbed/templates/secret-signalilo.yaml new file mode 100644 index 0000000..f849427 --- /dev/null +++ b/deploy/charts/scrubbed/templates/secret-signalilo.yaml @@ -0,0 +1,12 @@ +{{- if and .Values.signalilo.enabled .Values.signalilo.testSecret -}} +kind: Secret +apiVersion: v1 +metadata: + name: {{ include "scrubbed.fullname" . }}-signalilo + labels: + {{- include "scrubbed.labels" . | nindent 4 }} + app.kubernetes.io/component: signalilo +stringData:: + SIGNALILO_ALERTMANAGER_BEARER_TOKEN: foo + SIGNALILO_ICINGA_PASSWORD: bar +{{- end -}} diff --git a/deploy/charts/scrubbed/templates/service-scrubbed.yaml b/deploy/charts/scrubbed/templates/service-scrubbed.yaml new file mode 100644 index 0000000..78da68a --- /dev/null +++ b/deploy/charts/scrubbed/templates/service-scrubbed.yaml @@ -0,0 +1,23 @@ +apiVersion: v1 +kind: Service +metadata: + name: {{ .Values.scrubbed.serviceName }} + labels: + {{- include "scrubbed.labels" . | nindent 4 }} + app.kubernetes.io/component: scrubbed +spec: + internalTrafficPolicy: Cluster + ipFamilyPolicy: SingleStack + ports: + - name: scrubbed + port: {{ .Values.scrubbed.listenPort }} + protocol: TCP + targetPort: {{ .Values.scrubbed.listenPort }} + selector: + {{- include "scrubbed.selectorLabels" . | nindent 4 }} + app.kubernetes.io/component: scrubbed + sessionAffinity: ClientIP + sessionAffinityConfig: + clientIP: + timeoutSeconds: 10800 + type: ClusterIP diff --git a/deploy/charts/scrubbed/templates/service-signalilo.yaml b/deploy/charts/scrubbed/templates/service-signalilo.yaml new file mode 100644 index 0000000..c560c34 --- /dev/null +++ b/deploy/charts/scrubbed/templates/service-signalilo.yaml @@ -0,0 +1,25 @@ +{{- if .Values.signalilo.enabled -}} +apiVersion: v1 +kind: Service +metadata: + name: {{ .Values.signalilo.serviceName }} + labels: + {{- include "scrubbed.labels" . | nindent 4 }} + app.kubernetes.io/component: signalilo +spec: + internalTrafficPolicy: Cluster + ipFamilyPolicy: SingleStack + ports: + - name: signalilo + port: {{ .Values.signalilo.listenPort }} + protocol: TCP + targetPort: {{ .Values.signalilo.listenPort }} + selector: + {{- include "scrubbed.selectorLabels" . | nindent 4 }} + app.kubernetes.io/component: scrubbed + sessionAffinity: ClientIP + sessionAffinityConfig: + clientIP: + timeoutSeconds: 10800 + type: ClusterIP +{{- end -}} diff --git a/deploy/charts/scrubbed/templates/serviceaccount.yaml b/deploy/charts/scrubbed/templates/serviceaccount.yaml new file mode 100644 index 0000000..f0c3c4f --- /dev/null +++ b/deploy/charts/scrubbed/templates/serviceaccount.yaml @@ -0,0 +1,7 @@ +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ include "scrubbed.fullname" . }} + labels: + {{- include "scrubbed.labels" . | nindent 4 }} + app.kubernetes.io/component: scrubbed diff --git a/deploy/charts/scrubbed/values.yaml b/deploy/charts/scrubbed/values.yaml new file mode 100644 index 0000000..a6ecf18 --- /dev/null +++ b/deploy/charts/scrubbed/values.yaml @@ -0,0 +1,86 @@ +# Default values for scrubbed chart. +# This is a YAML-formatted file. +# Declare variables to be passed into your templates. + +image: + # -- Scrubbed image repository + repository: quay.io/adfinis/scrubbed + # -- Scrubbed image version + tag: ~ + +# -- Number of replicas +replicaCount: 1 + +scrubbed: + # -- Space separated list of alert annotations to keep + alertAnnotations: "" + # -- Space separated list of alert labels to keep + alertLabels: "alertname severity" + # -- Space separated list of common annotations to keep + commonAnnotations: "" + # -- Space separated list of common labels to keep + commonLabels: "alertname severity" + # -- Space separated list of group labels to keep + groupLabels: "" + # -- Destination URL to send scrubbed alerts to + destinationURL: "http://alert-receiver:8888/webhook" + # -- Listener host of Scrubbed service + listenHost: "0.0.0.0" + # -- Listener port of Scrubbed service + listenPort: "8080" + # -- Scrubbed log level + logLevel: "INFO" + # -- Resource limits and requests for scrubbed + resources: + {} + # We usually recommend not to specify default resources and to leave this as a conscious + # choice for the user. This also increases chances charts run on environments with little + # resources, such as Minikube. If you do want to specify resources, uncomment the following + # lines, adjust them as necessary, and remove the curly braces after 'resources:'. + # limits: + # cpu: 100m + # memory: 32Mi + # requests: + # cpu: 10m + # memory: 16Mi + # -- Scrubbed service name + serviceName: scrubbed + +signalilo: + # -- Enable Signalilo sidecar. If enabled, use image scrubbed-signalilo. + enabled: false + # -- The name of an annotation to retrieve the plugin_output from + alertmanagerPluginOutputAnnotations: | + description + message + # -- Listen port of Signalilo service + listenPort: "8888" + # -- A PEM string of the trusted CA certificate for the Icinga2 API certificate + icingaCA: "" + # -- If true, enable debugging mode in Icinga client + debug: "0" + # -- Name of the Servicehost in Icinga2 + icingaHostname: "" + # -- URL of the Icinga API. It's possible to specify one or more URLs. The Parameter content will be split on newline character + icingaURL: "" + # -- Authentication against Icinga2 API. + icingaUsername: "" + # -- UUID which identifies the Signalilo instance. + icingaUUID: "00000000-0000-0000-0000-000000000000" + # -- Resource limits and requests for scrubbed + resources: + {} + # We usually recommend not to specify default resources and to leave this as a conscious + # choice for the user. This also increases chances charts run on environments with little + # resources, such as Minikube. If you do want to specify resources, uncomment the following + # lines, adjust them as necessary, and remove the curly braces after 'resources:'. + # limits: + # cpu: 100m + # memory: 32Mi + # requests: + # cpu: 10m + # memory: 16Mi + # -- Signalilo service name + serviceName: signalilo + # -- generate secret for CI testing, if false provide your own. Required keys are SIGNALILO_ALERTMANAGER_BEARER_TOKEN and SIGNALILO_ICINGA_PASSWORD + testSecret: false diff --git a/deploy/kustomize/base/configmap.yaml b/deploy/kustomize/base/configmap.yaml index 4af8ac7..cb4cb50 100644 --- a/deploy/kustomize/base/configmap.yaml +++ b/deploy/kustomize/base/configmap.yaml @@ -11,4 +11,5 @@ data: SCRUBBED_DESTINATION_URL: 'http://receiver:8888/webhook' SCRUBBED_GROUP_LABELS: '' SCRUBBED_LISTEN_PORT: '8080' + SCRUBBED_LISTEN_HOST: '0.0.0.0' SCRUBBED_LOG_LEVEL: INFO