From 7d2156fca05dee064afb26c6976b0d634d4c3df4 Mon Sep 17 00:00:00 2001 From: Markos Kandylis Date: Fri, 28 Feb 2025 19:32:24 +0000 Subject: [PATCH 1/2] Creating a helm chart for application sets Signed-off-by: Markos Kandylis --- charts/application-sets/.helmignore | 23 ++ charts/application-sets/Chart.yaml | 24 ++ charts/application-sets/README.md | 0 charts/application-sets/addons.yaml | 231 ++++++++++++++++++ charts/application-sets/monitoring.yaml | 47 ++++ charts/application-sets/resources.yaml | 15 ++ .../templates/_application_set.tpl | 58 +++++ .../templates/_git_matrix.tpl | 34 +++ .../application-sets/templates/_helpers.tpl | 48 ++++ .../templates/_pod_identity.tpl | 35 +++ .../templates/application-set.yaml | 173 +++++++++++++ charts/application-sets/values.yaml | 27 ++ 12 files changed, 715 insertions(+) create mode 100644 charts/application-sets/.helmignore create mode 100644 charts/application-sets/Chart.yaml create mode 100644 charts/application-sets/README.md create mode 100644 charts/application-sets/addons.yaml create mode 100644 charts/application-sets/monitoring.yaml create mode 100644 charts/application-sets/resources.yaml create mode 100644 charts/application-sets/templates/_application_set.tpl create mode 100644 charts/application-sets/templates/_git_matrix.tpl create mode 100644 charts/application-sets/templates/_helpers.tpl create mode 100644 charts/application-sets/templates/_pod_identity.tpl create mode 100644 charts/application-sets/templates/application-set.yaml create mode 100644 charts/application-sets/values.yaml diff --git a/charts/application-sets/.helmignore b/charts/application-sets/.helmignore new file mode 100644 index 0000000..0e8a0eb --- /dev/null +++ b/charts/application-sets/.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/charts/application-sets/Chart.yaml b/charts/application-sets/Chart.yaml new file mode 100644 index 0000000..3546ee5 --- /dev/null +++ b/charts/application-sets/Chart.yaml @@ -0,0 +1,24 @@ +apiVersion: v2 +name: application-sets +description: A Helm chart for Kubernetes + +# A chart can be either an 'application' or a 'library' chart. +# +# Application charts are a collection of templates that can be packaged into versioned archives +# to be deployed. +# +# Library charts provide useful utilities or functions for the chart developer. They're included as +# a dependency of application charts to inject those utilities and functions into the rendering +# pipeline. Library charts do not define any templates and therefore cannot be deployed. +type: application + +# This is the chart version. This version number should be incremented each time you make changes +# to the chart and its templates, including the app version. +# Versions are expected to follow Semantic Versioning (https://semver.org/) +version: 0.1.0 + +# This is the version number of the application being deployed. This version number should be +# incremented each time you make changes to the application. Versions are not expected to +# follow Semantic Versioning. They should reflect the version the application is using. +# It is recommended to use it with quotes. +appVersion: "1.16.0" diff --git a/charts/application-sets/README.md b/charts/application-sets/README.md new file mode 100644 index 0000000..e69de29 diff --git a/charts/application-sets/addons.yaml b/charts/application-sets/addons.yaml new file mode 100644 index 0000000..1fe783e --- /dev/null +++ b/charts/application-sets/addons.yaml @@ -0,0 +1,231 @@ +argocd: + enabled: false + chartName: argo-cd + namespace: argocd + releaseName: argocd + defaultVersion: "7.7.8" + chartRepository: "https://argoproj.github.io/argo-helm" + selector: + matchExpressions: + - key: enable_argocd + operator: In + values: ['true'] +iam-chart: + enabled: false + enableAckPodIdentity: false + namespace: ack-system + defaultVersion: "1.3.13" + chartNamespace: aws-controllers-k8s + chartRepository: public.ecr.aws + selector: + matchExpressions: + - key: enable_ack_iam + operator: In + values: ['true'] + environments: + - selector: + environment: staging + tenant: tenant1 + chartVersion: "7.6.12" + valuesObject: + aws: + region: '{{.metadata.annotations.aws_region}}' + serviceAccount: + name: '{{.metadata.annotations.ack_iam_service_account}}' +ack-eks: + enabled: false + enableAckPodIdentity: false + namespace: ack-system + chartName: eks-chart + defaultVersion: "1.5.1" + chartNamespace: aws-controllers-k8s + chartRepository: public.ecr.aws + selector: + matchExpressions: + - key: enable_ack_eks + operator: In + values: ['true'] + valuesObject: + aws: + region: '{{.metadata.annotations.aws_region}}' + serviceAccount: + name: '{{.metadata.annotations.ack_eks_service_account}}' +ack-acm: + enabled: true + enableAckPodIdentity: true + namespace: ack-system + chartName: acm-chart + defaultVersion: "1.0.2" + chartNamespace: aws-controllers-k8s + chartRepository: public.ecr.aws + selector: + matchExpressions: + - key: enable_ack_acm + operator: In + values: ['true'] + valuesObject: + aws: + region: '{{.metadata.annotations.aws_region}}' + serviceAccount: + name: 'ack-acm-controller' + annotations: + eks.amazonaws.com/role-arn: '{{default "" (index .metadata.annotations "ack_acm_role_arn")}}' +route53-chart: + enabled: false + enableAckPodIdentity: false + namespace: ack-system + chartName: route53-chart + defaultVersion: "0.0.20" + chartNamespace: aws-controllers-k8s + chartRepository: public.ecr.aws + selector: + matchExpressions: + - key: enable_route53_controller + operator: In + values: ['true'] + valuesObject: + aws: + region: '{{.metadata.annotations.aws_region}}' + serviceAccount: + name: 'route53-controller' + annotations: + eks.amazonaws.com/role-arn: '{{default "" (index .metadata.annotations "ack_route53_controller_role_arn")}}' +external-secrets: + enabled: true + enableAckPodIdentity: false + namespace: external-secrets + chartName: external-secrets + defaultVersion: "0.10.3" + chartRepository: "https://charts.external-secrets.io" + additionalResources: + path: "charts/fleet-secret" + type: "ecr-token" + helm: + releaseName: ecr-token + selector: + matchExpressions: + - key: enable_external_secrets + operator: In + values: ['true'] + valuesObject: + installCRDs: '{{default toBool(true) toBool((index .metadata.labels "use_external_secrets"))}}' + serviceAccount: + name: "external-secrets-sa" + annotations: + eks.amazonaws.com/role-arn: '{{default "" (index .metadata.annotations "external_secrets_iam_role_arn")}}' +aws-load-balancer-controller: + enabled: true + enableAckPodIdentity: true + namespace: kube-system + defaultVersion: "1.8.4" + chartRepository: "https://aws.github.io/eks-charts" + selector: + matchExpressions: + - key: enable_aws_load_balancer_controller + operator: In + values: ['true'] + valuesObject: + serviceAccount: + name: "aws-load-balancer-controller-sa" + vpcId: '{{.metadata.annotations.aws_vpc_id}}' + clusterName: '{{.name}}' + ignoreDifferences: + - kind: Secret + name: aws-load-balancer-tls + jsonPointers: [/data] + - group: admissionregistration.k8s.io + kind: MutatingWebhookConfiguration + jqPathExpressions: ['.webhooks[].clientConfig.caBundle'] + - group: admissionregistration.k8s.io + kind: ValidatingWebhookConfiguration + jqPathExpressions: ['.webhooks[].clientConfig.caBundle'] +metrics-server: + enabled: false + namespace: kube-system + defaultVersion: "3.11.0" + chartRepository: "https://kubernetes-sigs.github.io/metrics-server" + selector: + matchExpressions: + - key: enable_metrics_server + operator: In + values: ['true'] +karpenter: + enabled: false + enableAckPodIdentity: false + releaseName: karpenter + namespace: 'karpenter' + chartName: karpenter/karpenter + chartRepository: public.ecr.aws + defaultVersion: "1.0.4" + selector: + matchExpressions: + - key: enable_karpenter + operator: In + values: ['true'] + valuesObject: + settings: + clusterName: '{{.metadata.annotations.aws_cluster_name}}' + interruptionQueue: '{{.metadata.annotations.karpenter_sqs_queue_name}}' + serviceAccount: + name: '{{.metadata.annotations.karpenter_service_account}}' + annotations: + eks.amazonaws.com/role-arn: '{{.metadata.annotations.karpenter_iam_role_arn}}' +aws_efs_csi_driver: + enabled: false + enableAckPodIdentity: false + releaseName: aws-efs-csi-driver + namespace: "kube-sytem" + chartName: aws-efs-csi-driver + chartRepository: https://kubernetes-sigs.github.io/aws-efs-csi-driver + defaultVersion: "3.0.7" + selector: + matchExpressions: + - key: enable_aws_efs_csi_driver + operator: In + values: ['true'] + valuesObject: + controller: + serviceAccount: + name: '{{default "" (index .metadata.annotations aws_efs_csi_driver_controller_service_account)}}' + annotations: + eks.amazonaws.com/role-arn: '{{default "" (index .metadata.annotations aws_efs_csi_driver_iam_role_arn)}}' + node: + serviceAccount: + name: '{{.metadata.annotations.aws_efs_csi_driver_node_service_account}}' + annotations: + eks.amazonaws.com/role-arn: '{{.metadata.annotations.aws_efs_csi_driver_iam_role_arn}}' +kro: + enabled: false + namespace: kro-system + defaultVersion: "0.2.1" + chartName: kro + chartNamespace: kro + chartRepository: ghcr.io/kro-run + selector: + matchExpressions: + - key: enable_kro + operator: In + values: ['true'] +kro-resource-groups: + enabled: false + type: manifest + namespace: kro-resource-groups + defaultVersion: "0.1.0" + path: kro/resource-groups + selector: + matchExpressions: + - key: enable_kro_resource_groups + operator: In + values: ['true'] +external-dns: + enabled: false + releaseName: external-dns + namespace: '{{.metadata.annotations.external_dns_namespace}}' + chartName: external-dns + chartRepository: https://kubernetes-sigs.github.io/external-dns + defaultVersion: "1.14.5" + selector: + matchExpressions: + - key: enable_external_dns + operator: In + values: ['true'] \ No newline at end of file diff --git a/charts/application-sets/monitoring.yaml b/charts/application-sets/monitoring.yaml new file mode 100644 index 0000000..5214047 --- /dev/null +++ b/charts/application-sets/monitoring.yaml @@ -0,0 +1,47 @@ +adot_collector: + enableACK: true + enabled: true + namespace: '{{default "adot-collector-kubeprometheus" (index .metadata.annotations "adot_collector_namespace")}}' + defaultVersion: "1.0.0" + path: charts/adot-collector + selector: + matchExpressions: + - key: enable_adot_collector + operator: In + values: ['true'] + valuesObject: + ekscluster: '{{.metadata.annotations.aws_cluster_name}}' + accountId: '{{.metadata.annotations.aws_account_id}}' + region: '{{.metadata.annotations.aws_region}}' + ampurl: '{{.metadata.annotations.amp_endpoint_url}}api/v1/remote_write' + serviceAccount: '{{.metadata.annotations.adot_collector_serviceaccount}}' +amp-prometheus: + enabled: true + enableACK: true + ackPodIdentity: + repoURL: "testPath" + chart: "chartName" + chartVersion: "v1" + releaseName: amp-prometheus + namespace: '{{default "amp-prometheus" (index .metadata.annotations "amp_prometheus_namespace")}}' + chartName: prometheus + chartRepository: https://prometheus-community.github.io/helm-charts + defaultVersion: "27.3.1" + valuesObject: + serviceAccounts: + server: + name: '{{default "amp-prometheus-server-sa" (index .metadata.annotations "amp_prometheus_server_sa")}}' + annotations: + eks.amazonaws.com/role-arn: '{{default "" (index .metadata.annotations "amp_prometheus_iam_role_arn")}}' + server: + remoteWrite: + - + url: '{{.metadata.annotations.amp_endpoint_url}}api/v1/remote_write' + sigv4: + region: '{{.metadata.annotations.aws_region}}' + role_arn: '{{default "" (index .metadata.annotations "amp_prometheus_crossaccount_role")}}' + selector: + matchExpressions: + - key: enable_amp_prometheus + operator: In + values: ['true'] \ No newline at end of file diff --git a/charts/application-sets/resources.yaml b/charts/application-sets/resources.yaml new file mode 100644 index 0000000..c9e4fcf --- /dev/null +++ b/charts/application-sets/resources.yaml @@ -0,0 +1,15 @@ +karpenter-resources: + enabled: true + chartName: karpenter-resources + defaultVersion: "1.0.0" + path: 'charts/karpenter-resources' + namespace: karpenter-resources + selector: + matchExpressions: + - key: enable_karpenter_resources + operator: In + values: ['true'] + valuesObject: + nodeClases: + role: '{{.metadata.annotations.karpenter_node_iam_role_name}}' + clusterName: '{{.metadata.annotations.aws_cluster_name}}' diff --git a/charts/application-sets/templates/_application_set.tpl b/charts/application-sets/templates/_application_set.tpl new file mode 100644 index 0000000..e4c29ff --- /dev/null +++ b/charts/application-sets/templates/_application_set.tpl @@ -0,0 +1,58 @@ +{{/* +Template to generate additional resources configuration +*/}} +{{- define "application-sets.additionalResources" -}} +{{- $chartName := .chartName -}} +{{- $chartConfig := .chartConfig -}} +{{- $valueFiles := .valueFiles -}} +{{- $additionalResourcesType := .additionalResourcesType -}} +{{- $additionalResourcesPath := .path -}} +{{- $values := .values -}} +{{- if $chartConfig.additionalResources.path }} +- repoURL: {{ $values.repoURLGit | squote }} + targetRevision: {{ $values.repoURLGitRevision | squote }} + path: {{- if eq $additionalResourcesType "manifests" }} + '{{ $values.repoURLGitBasePath }}{{ if $values.useValuesFilePrefix }}{{ $values.valuesFilePrefix }}{{ end }}clusters/{{`{{.nameNormalized}}`}}/{{ $chartConfig.additionalResources.manifestPath }}' + {{- else }} + {{ $chartConfig.additionalResources.path | squote }} + {{- end}} +{{- end }} +{{- if $chartConfig.additionalResources.chart }} +- repoURL: '{{$chartConfig.additionalResources.repoURL}}' + chart: '{{$chartConfig.additionalResources.chart}}' + targetRevision: '{{$chartConfig.additionalResources.chartVersion }}' +{{- end }} +{{- if $chartConfig.additionalResources.helm }} + helm: + releaseName: '{{`{{ .name }}`}}-{{ $chartConfig.additionalResources.helm.releaseName }}' + {{- if $chartConfig.additionalResources.helm.valuesObject }} + valuesObject: + {{- $chartConfig.additionalResources.helm.valuesObject | toYaml | nindent 6 }} + {{- end }} + ignoreMissingValueFiles: true + valueFiles: + {{- include "application-sets.valueFiles" (dict + "nameNormalize" $chartName + "valueFiles" $valueFiles + "values" $values + "chartType" $additionalResourcesType) | nindent 6 }} +{{- end }} +{{- end }} + + +{{/* +Define the values path for reusability +*/}} +{{- define "application-sets.valueFiles" -}} +{{- $nameNormalize := .nameNormalize -}} +{{- $chartConfig := .chartConfig -}} +{{- $valueFiles := .valueFiles -}} +{{- $chartType := .chartType -}} +{{- $values := .values -}} +{{- with .valueFiles }} +{{- range . }} +- $values/{{ $values.repoURLGitBasePath }}/{{ . }}/{{ $nameNormalize }}{{ if $chartType }}/{{ $chartType }}{{ end }}/{{ if $chartConfig.valuesFileName }}{{ $chartConfig.valuesFileName }}{{ else }}values.yaml{{ end }} +- $values/{{ $values.repoURLGitBasePath }}/{{ if $values.useValuesFilePrefix }}{{ $values.valuesFilePrefix }}{{ end }}{{ . }}/{{ $nameNormalize }}{{ if $chartType }}/{{ $chartType }}{{ end }}/{{ if $chartConfig.valuesFileName }}{{ $chartConfig.valuesFileName }}{{ else }}values.yaml{{ end }} +{{- end }} +{{- end }} +{{- end }} diff --git a/charts/application-sets/templates/_git_matrix.tpl b/charts/application-sets/templates/_git_matrix.tpl new file mode 100644 index 0000000..61353d3 --- /dev/null +++ b/charts/application-sets/templates/_git_matrix.tpl @@ -0,0 +1,34 @@ + {{/* +Template creating git matrix generator +*/}} +{{- define "application-sets.git-matrix" -}} +{{- $chartName := .chartName -}} +{{- $chartConfig := .chartConfig -}} +{{- $repoURLGit := .repoURLGit -}} +{{- $repoURLGitRevision := .repoURLGitRevision -}} +{{- $selectors := .selectors -}} +{{- $useSelectors := .useSelectors -}} +generators: +- matrix: + generators: + - clusters: + selector: + matchLabels: + argocd.argoproj.io/secret-type: cluster + {{- if $selectors }} + {{- toYaml $selectors | nindent 16 }} + {{- end }} + {{- if $chartConfig.selectorMatchLabels }} + {{- toYaml $chartConfig.selectorMatchLabels | nindent 18 }} + {{- end }} + {{- if and $chartConfig.selector $useSelectors }} + {{- toYaml $chartConfig.selector | nindent 16 }} + {{- end }} + values: + chart: {{ $chartConfig.chartName | default $chartName | quote }} + - git: + repoURL: {{ $repoURLGit | squote }} + revision: {{ $repoURLGitRevision | squote }} + files: + - path: {{ $chartConfig.matrixPath | squote }} +{{- end }} \ No newline at end of file diff --git a/charts/application-sets/templates/_helpers.tpl b/charts/application-sets/templates/_helpers.tpl new file mode 100644 index 0000000..c705613 --- /dev/null +++ b/charts/application-sets/templates/_helpers.tpl @@ -0,0 +1,48 @@ +{{/* +Expand the name of the chart. Defaults to `.Chart.Name` or `nameOverride`. +*/}} +{{- define "application-sets.name" -}} +{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Generate a fully qualified app name. +If `fullnameOverride` is defined, it uses that; otherwise, it constructs the name based on `Release.Name` and chart name. +*/}} +{{- define "application-sets.fullname" -}} +{{- if .Values.fullnameOverride }} +{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- printf "%s-%s" .Release.Name (default .Chart.Name .Values.nameOverride) | trunc 63 | trimSuffix "-" }} +{{- end }} +{{- end }} + +{{/* +Create chart name and version, useful for labels. +*/}} +{{- define "application-sets.chart" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Common labels for the ApplicationSet, including version and managed-by labels. +*/}} +{{- define "application-sets.labels" -}} +helm.sh/chart: {{ include "application-sets.chart" . }} +app.kubernetes.io/name: {{ include "application-sets.name" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +{{- if .Chart.AppVersion }} +app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} +{{- end }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +{{- end }} + +{{/* +Common Helm and Kubernetes Annotations +*/}} +{{- define "application-sets.annotations" -}} +helm.sh/chart: {{ include "application-sets.chart" . }} +{{- if .Values.annotations }} +{{ toYaml .Values.annotations }} +{{- end }} +{{- end }} diff --git a/charts/application-sets/templates/_pod_identity.tpl b/charts/application-sets/templates/_pod_identity.tpl new file mode 100644 index 0000000..065f7c9 --- /dev/null +++ b/charts/application-sets/templates/_pod_identity.tpl @@ -0,0 +1,35 @@ +{{/* +Template to generate pod-identity configuration +*/}} +{{- define "application-sets.pod-identity" -}} +{{- $chartName := .chartName -}} +{{- $chartConfig := .chartConfig -}} +{{- $valueFiles := .valueFiles -}} +{{- $values := .values -}} +{{- with merge (default dict $values.ackPodIdentity) (default dict $chartConfig.ackPodIdentity) }} +{{- if .path }} +- repoURL: '{{ $values.repoURLGit }}' + targetRevision: '{{ $values.repoURLGitRevision }}' + path: {{default "charts/pod-identity" $values.ackPodIdentity.path }} +{{- else if .repoURL }} +- repoURL: '{{ $values.ackPodIdentity.repoURL }}' + chart: '{{ $values.ackPodIdentity.chart }}' + targetRevision: '{{ $values.ackPodIdentity.chartVersion }}' +{{- end }} +{{- end }} + helm: + releaseName: '{{`{{ .name }}`}}-{{ $chartConfig.chartName | default $chartName }}' + valuesObject: + create: '{{`{{default "`}}{{ $chartConfig.enableAckPodIdentity }}{{`" (index .metadata.annotations "ack_create")}}`}}' + region: '{{`{{ .metadata.annotations.aws_region }}`}}' + accountId: '{{`{{ .metadata.annotations.aws_account_id}}`}}' + podIdentityAssociation: + clusterName: '{{`{{ .name }}`}}' + namespace: '{{ default $chartConfig.namespace .namespace }}' + ignoreMissingValueFiles: true + valueFiles: + {{- include "application-sets.valueFiles" (dict + "nameNormalize" $chartName + "valueFiles" $valueFiles + "values" $values "chartType" "pod-identity") | nindent 6 }} +{{- end }} diff --git a/charts/application-sets/templates/application-set.yaml b/charts/application-sets/templates/application-set.yaml new file mode 100644 index 0000000..6a000b8 --- /dev/null +++ b/charts/application-sets/templates/application-set.yaml @@ -0,0 +1,173 @@ +{{- $values := .Values }} +{{- $chartType := .Values.chartType }} +{{- $namespace := .Values.namespace }} +{{- $syncPolicy := .Values.syncPolicy -}} +{{- $syncPolicyAppSet := .Values.syncPolicyAppSet -}} +{{- $goTemplateOptions := .Values.goTemplateOptions -}} +{{- $repoURLGit := .Values.repoURLGit -}} +{{- $repoURLGitRevision := .Values.repoURLGitRevision -}} +{{- $repoURLGitBasePath := .Values.repoURLGitBasePath -}} +{{- $valueFiles := .Values.valueFiles -}} +{{- $valuesFilePrefix := .Values.valuesFilePrefix -}} +{{- $useValuesFilePrefix := (default false .Values.useValuesFilePrefix ) -}} +{{- $useSelectors:= .Values.useSelectors -}} +{{- $globalSelectors := .Values.globalSelectors -}} + +{{- range $chartName, $chartConfig := .Values }} +{{- if and (kindIs "map" $chartConfig) (hasKey $chartConfig "enabled") }} +{{- if eq (toString $chartConfig.enabled) "true" }} +{{- $nameNormalize := printf "%s" $chartName | replace "_" "-" | trunc 63 | trimSuffix "-" -}} +apiVersion: argoproj.io/v1alpha1 +kind: ApplicationSet +metadata: + name: {{ $nameNormalize }} + namespace: {{ default "argocd" $namespace }} + annotations: + {{- include "application-sets.annotations" $ | nindent 4 }} + {{- if $chartConfig.annotationsAppSet }}{{- toYaml $chartConfig.annotationsAppSet | nindent 4 }}{{- end }} + labels: + {{- include "application-sets.labels" $ | nindent 4 }} + {{- if $chartConfig.labelsAppSet }}{{- toYaml $chartConfig.labelsAppSet | nindent 4 }}{{- end }} +spec: + goTemplate: true + {{- if $chartConfig.goTemplateOptions }} + goTemplateOptions: + {{ toYaml $chartConfig.goTemplateOptions | nindent 2 }} + {{- else }} + goTemplateOptions: {{ default (list "missingkey=error") $goTemplateOptions }} + {{- end }} + {{- if $chartConfig.syncPolicyAppSet }} + syncPolicy: + {{- toYaml $chartConfig.syncPolicyAppSet | nindent 4 }} + {{- else }} + syncPolicy: + {{- toYaml $syncPolicyAppSet | nindent 4 }} + {{- end }} + {{- if $chartConfig.gitMatrix }} + {{ include "application-sets.git-matrix" (dict + "chartName" $nameNormalize "chartConfig" $chartConfig + "repoURLGit" $repoURLGit "repoURLGitRevision" $repoURLGitRevision + "selectors" $globalSelectors "useSelectors" $useSelectors + ) | nindent 2 }} + {{- else }} + generators: + {{- if $chartConfig.environments }} + - merge: + mergeKeys: [server] + generators: + {{- end }} + - clusters: + selector: + matchLabels: + argocd.argoproj.io/secret-type: cluster + {{- if $globalSelectors }} + {{- toYaml $globalSelectors | nindent 18 }} + {{- end }} + {{- if $chartConfig.selectorMatchLabels }} + {{- toYaml $chartConfig.selectorMatchLabels | nindent 18 }} + {{- end }} + {{- if and $chartConfig.selector $useSelectors }} + {{- toYaml $chartConfig.selector | nindent 16 }} + {{- end }} + {{- if not $chartConfig.resourceGroup }} + values: + addonChart: {{ $chartConfig.chartName | default $nameNormalize | quote }} + {{- if $chartConfig.defaultVersion }} + addonChartVersion: {{ $chartConfig.defaultVersion | quote }} + {{- end }} + {{- if $chartConfig.chartRepository }} + addonChartRepository: {{ $chartConfig.chartRepository | quote }} + {{- end }} + {{- if $chartConfig.chartNamespace }} + addonChartRepositoryNamespace: {{ $chartConfig.chartNamespace | quote }} + chart: {{ printf "%s/%s" $chartConfig.chartNamespace ($chartConfig.chartName | default $nameNormalize) | quote }} + {{- else }} + chart: {{ $chartConfig.chartName | default $nameNormalize | quote }} + {{- end }} + {{- end }} + {{- if $chartConfig.environments }} + {{- range $chartConfig.environments }} + - clusters: + selector: + matchLabels: + {{- toYaml .selector | nindent 18 }} + values: + addonChartVersion: {{ .chartVersion | default $chartConfig.defaultVersion | quote }} + {{- end }} + {{- end }} + {{- end }} + template: + metadata: + {{- if $chartConfig.appSetName }} + name: {{ $chartConfig.appSetName }} + {{- else }} + name: '{{ $nameNormalize }}-{{`{{ .name }}`}}' + {{- end }} + spec: + project: default + sources: + - repoURL: {{ $repoURLGit | squote}} + targetRevision: {{ $repoURLGitRevision | squote }} + ref: values + {{- if eq (toString $chartConfig.enableAckPodIdentity) "true" }} + {{ include "application-sets.pod-identity" (dict + "chartName" ($chartConfig.chartName | default $nameNormalize) + "valueFiles" $valueFiles + "chartConfig" $chartConfig "values" $values ) | nindent 6 }} + {{- end }} + {{- if $chartConfig.path }} + - repoURL: {{ $repoURLGit | squote }} + path: {{$chartConfig.path | squote }} + targetRevision: {{ $repoURLGitRevision | squote }} + {{- else }} + - repoURL: '{{`{{ .values.addonChartRepository }}`}}' + chart: '{{`{{ .values.chart }}`}}' + targetRevision: '{{`{{.values.addonChartVersion }}`}}' + {{- end }} + {{- if ne (default "" $chartConfig.type) "manifest" }} + helm: + releaseName: {{ default "{{ .values.addonChart }}" $chartConfig.releaseName | squote }} + ignoreMissingValueFiles: true + {{- if $chartConfig.valuesObject }} + valuesObject: + {{- $chartConfig.valuesObject | toYaml | nindent 12 }} + {{- end }} + {{- if $valueFiles }} + valueFiles: + {{- include "application-sets.valueFiles" (dict + "nameNormalize" ($chartConfig.chartName | default $nameNormalize) + "chartConfig" $chartConfig + "valueFiles" $valueFiles "values" $values) | nindent 12 }} + {{- end }} + {{- if $chartConfig.additionalResources}} + {{ include "application-sets.additionalResources" (dict + "chartName" ($chartConfig.chartName | default $nameNormalize) + "valueFiles" $valueFiles + "chartConfig" $chartConfig + "values" $values + "additionalResourcesType" $chartConfig.additionalResources.type + "additionalResourcesPath" $chartConfig.additionalResources.path ) | nindent 6 }} + {{- end}} + {{- end }} + destination: + namespace: '{{ $chartConfig.namespace }}' + name: '{{`{{ .name }}`}}' + {{- if $chartConfig.syncPolicy }} + syncPolicy: + {{- toYaml $chartConfig.syncPolicy | nindent 8 }} + {{ else }} + syncPolicy: + {{- toYaml $syncPolicy | nindent 8 }} + {{- end }} + {{- with $chartConfig.ignoreDifferences }} + ignoreDifferences: + {{- toYaml . | nindent 8 }} + {{- end }} + {{- if $chartConfig.ignoreDifferences}} + ignoreDifferences: + {{- $chartConfig.ignoreDifferences | toYaml | nindent 8 }} + {{- end }} +--- +{{- end }} +{{- end }} +{{- end }} diff --git a/charts/application-sets/values.yaml b/charts/application-sets/values.yaml new file mode 100644 index 0000000..64ff13c --- /dev/null +++ b/charts/application-sets/values.yaml @@ -0,0 +1,27 @@ +syncPolicy: + automated: + selfHeal: false + allowEmpty: true + prune: false + retry: + limit: -1 # number of failed sync attempt retries; unlimited number of attempts if less than 0 + backoff: + duration: 5s # the amount to back off. Default unit is seconds, but could also be a duration (e.g. "2m", "1h") + factor: 2 # a factor to multiply the base duration after each failed retry + maxDuration: 10m # the maximum amount of time allowed for the backoff strategy + syncOptions: + - CreateNamespace=true + - ServerSideApply=true # Big CRDs. +syncPolicyAppSet: + preserveResourcesOnDeletion: true +useSelectors: true +repoURLGit: '{{.metadata.annotations.addons_repo_url}}' +repoURLGitRevision: '{{.metadata.annotations.addons_repo_revision}}' +repoURLGitBasePath: '{{.metadata.annotations.addons_repo_basepath}}' +valueFiles: + - default/addons + - clusters/{{.nameNormalized}}/addons +useValuesFilePrefix: true +valuesFilePrefix: '{{.metadata.labels.tenant}}/' +ackPodIdentity: + path: "charts/pod-identity" \ No newline at end of file From bceb9602a33442d0b15c3bc3b82bbe3a8a13e03b Mon Sep 17 00:00:00 2001 From: Markos Kandylis Date: Mon, 3 Mar 2025 14:10:35 +0000 Subject: [PATCH 2/2] Adding pod identity chart Signed-off-by: Markos Kandylis --- charts/pod-identity/.helmignore | 23 ++++++ charts/pod-identity/Chart.yaml | 24 ++++++ charts/pod-identity/templates/_helpers.tpl | 74 +++++++++++++++++++ .../templates/pod-identity-association.yaml | 27 +++++++ .../templates/pod-identity-policy.yaml | 56 ++++++++++++++ .../templates/pod-identity-role.yaml | 68 +++++++++++++++++ charts/pod-identity/values.yaml | 61 +++++++++++++++ 7 files changed, 333 insertions(+) create mode 100644 charts/pod-identity/.helmignore create mode 100644 charts/pod-identity/Chart.yaml create mode 100644 charts/pod-identity/templates/_helpers.tpl create mode 100644 charts/pod-identity/templates/pod-identity-association.yaml create mode 100644 charts/pod-identity/templates/pod-identity-policy.yaml create mode 100644 charts/pod-identity/templates/pod-identity-role.yaml create mode 100644 charts/pod-identity/values.yaml diff --git a/charts/pod-identity/.helmignore b/charts/pod-identity/.helmignore new file mode 100644 index 0000000..0e8a0eb --- /dev/null +++ b/charts/pod-identity/.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/charts/pod-identity/Chart.yaml b/charts/pod-identity/Chart.yaml new file mode 100644 index 0000000..aae321e --- /dev/null +++ b/charts/pod-identity/Chart.yaml @@ -0,0 +1,24 @@ +apiVersion: v2 +name: pod-identity +description: A Helm chart for Kubernetes + +# A chart can be either an 'application' or a 'library' chart. +# +# Application charts are a collection of templates that can be packaged into versioned archives +# to be deployed. +# +# Library charts provide useful utilities or functions for the chart developer. They're included as +# a dependency of application charts to inject those utilities and functions into the rendering +# pipeline. Library charts do not define any templates and therefore cannot be deployed. +type: application + +# This is the chart version. This version number should be incremented each time you make changes +# to the chart and its templates, including the app version. +# Versions are expected to follow Semantic Versioning (https://semver.org/) +version: 0.1.0 + +# This is the version number of the application being deployed. This version number should be +# incremented each time you make changes to the application. Versions are not expected to +# follow Semantic Versioning. They should reflect the version the application is using. +# It is recommended to use it with quotes. +appVersion: "1.16.0" diff --git a/charts/pod-identity/templates/_helpers.tpl b/charts/pod-identity/templates/_helpers.tpl new file mode 100644 index 0000000..235c382 --- /dev/null +++ b/charts/pod-identity/templates/_helpers.tpl @@ -0,0 +1,74 @@ +{{/* +Expand the name of the chart. +*/}} +{{- define "pod-identity.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 "pod-identity.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 "pod-identity.chart" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Common labels +*/}} +{{- define "pod-identity.labels" -}} +helm.sh/chart: {{ include "pod-identity.chart" . }} +{{ include "pod-identity.selectorLabels" . }} +{{- if .Chart.AppVersion }} +app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} +{{- end }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +{{- end }} + +{{/* +Selector labels +*/}} +{{- define "pod-identity.selectorLabels" -}} +app.kubernetes.io/name: {{ include "pod-identity.name" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +{{- end }} + +{{/* +Create the name of the service account to use +*/}} +{{- define "pod-identity.serviceAccountName" -}} +{{- if .Values.serviceAccount.create }} +{{- default (include "pod-identity.fullname" .) .Values.serviceAccount.name }} +{{- else }} +{{- default "default" .Values.serviceAccount.name }} +{{- end }} +{{- end }} +{{/* +Construct a dynamic ARN based on the values passed from ArgoCD or values.yaml. +*/}} +{{- define "pod-identity.resourceArn" -}} +arn:aws:{{ .resourceType }}:{{ .region }}:{{ .accountId }}:{{ .resourceName }} +{{- end }} +{{- define "pod-identity.accountID" -}} +{{ .accountId }} +{{- end }} +{{- define "pod-identity.region" -}} +{{ .region }} +{{- end }} \ No newline at end of file diff --git a/charts/pod-identity/templates/pod-identity-association.yaml b/charts/pod-identity/templates/pod-identity-association.yaml new file mode 100644 index 0000000..6f9b1e8 --- /dev/null +++ b/charts/pod-identity/templates/pod-identity-association.yaml @@ -0,0 +1,27 @@ +{{- if .Values.create | default false }} +{{- $cluster := .Values.podIdentityAssociation.clusterName -}} +{{- $namespace := .Values.podIdentityAssociation.namespace -}} +{{- $tags := .Values.podIdentityAssociation.tags -}} +{{- $root := . -}} +{{- $serviceAccounts := .Values.podIdentityAssociation.serviceAccounts -}} +{{- range $serviceAccounts }} +apiVersion: eks.services.k8s.aws/v1alpha1 +kind: PodIdentityAssociation +metadata: + name: "{{ include "pod-identity.fullname" $root }}-{{ . }}" + annotations: + argocd.argoproj.io/sync-wave: "-1" +spec: + clusterName: {{ $cluster }} + roleRef: + from: + name: "{{ include "pod-identity.fullname" $root }}" + namespace: {{ $namespace }} + serviceAccount: {{ . }} + {{- if $tags}} + tags: + {{- $tags| toYaml | nindent 10 }} + {{- end }} +--- +{{- end }} +{{- end }} diff --git a/charts/pod-identity/templates/pod-identity-policy.yaml b/charts/pod-identity/templates/pod-identity-policy.yaml new file mode 100644 index 0000000..71783e2 --- /dev/null +++ b/charts/pod-identity/templates/pod-identity-policy.yaml @@ -0,0 +1,56 @@ +{{- if and (.Values.create | default false) (.Values.podIdentityPolicyCreate | default false) }} +apiVersion: iam.services.k8s.aws/v1alpha1 +kind: Policy +metadata: + name: {{ include "pod-identity.fullname" . }} + annotations: + argocd.argoproj.io/sync-wave: "-3" +spec: + name: {{ include "pod-identity.fullname" . }} + description: {{ .Values.podIdentityPolicy.description }} + {{- if .Values.podIdentityPolicy.path }} + path: {{ .Values.podIdentityPolicy.path }} + {{- end }} + policyDocument: | + { + "Version": "2012-10-17", + "Statement": [ + {{- range $index, $policy := .Values.podIdentityPolicy.policies }} + { + "Effect": "Allow", + "Action": [ + {{- range $i, $action := $policy.actions }} + "{{ $action }}"{{ if not (eq (add $i 1) (len $policy.actions)) }},{{ end }} + {{- end }} + ], + "Resource": [ + {{- if $policy.customArn }} + "{{ $policy.customArn }}" + {{- else if eq $policy.resourceName "*" }} + "*" + {{- else }} + "arn:aws:{{ $policy.resourceType }}:{{ $.Values.region }}:{{ $.Values.accountId }}:{{ $policy.resourceName }}" + {{- end }} + ] + {{- if $policy.conditions }} + ,"Condition": { + {{- range $j, $condition := $policy.conditions }} + "{{ $condition.test }}": { + "{{ $condition.variable }}": [ + {{- range $k, $value := $condition.values }} + "{{ $value }}"{{ if not (eq (add $k 1) (len $condition.values)) }},{{ end }} + {{- end }} + ] + } + {{- end }} + } + {{- end }} + }{{ if not (eq (add $index 1) (len $.Values.podIdentityPolicy.policies)) }},{{ end }} + {{- end }} + ] + } + {{- if .Values.podIdentityPolicy.tags }} + tags: + {{- .Values.podIdentityPolicy.tags | toYaml | nindent 10 }} + {{- end }} +{{- end }} diff --git a/charts/pod-identity/templates/pod-identity-role.yaml b/charts/pod-identity/templates/pod-identity-role.yaml new file mode 100644 index 0000000..4cbb818 --- /dev/null +++ b/charts/pod-identity/templates/pod-identity-role.yaml @@ -0,0 +1,68 @@ +{{- if .Values.create | default false }} +apiVersion: iam.services.k8s.aws/v1alpha1 +kind: Role +metadata: + name: {{ include "pod-identity.fullname" . }} + annotations: + argocd.argoproj.io/sync-wave: "-2" +spec: + name: {{ include "pod-identity.fullname" . }} + assumeRolePolicyDocument: | + { + "Version": "2012-10-17", + "Statement": [ + { + "Effect": "Allow", + "Principal": { + "Service": "pods.eks.amazonaws.com" + }, + "Action": [ + "sts:TagSession", + "sts:AssumeRole" + ] + } + ] + } + description: {{ .Values.podIdentityRole.description }} + {{- if .Values.podIdentityRole.permissionsBoundary }} + permissionsBoundary: {{.Values.podIdentityRole.permissionsBoundary}} + {{- end }} + {{- if .Values.podIdentityRole.managedPolicies }} + policies: + {{- if and (.Values.podIdentityPolicyCreate | default false) .Values.podIdentityRole.managedPolicies }} + - "arn:aws:iam::{{ $.Values.accountId }}:policy/{{ include "pod-identity.fullname" . }}" + {{- end }} + {{- range .Values.podIdentityRole.managedPolicies }} + - "{{ . }}" + {{- end }} + + {{- else if .Values.podIdentityRole.policyRefs }} + policyRefs: + {{- if .Values.podIdentityPolicyCreate | default true }} + - from: + name: "{{ include "pod-identity.fullname" . }}" + {{- end }} + {{- range .Values.podIdentityRole.policyRefs }} + - from: + name: "{{ .name }}" + {{- if .namespace }} + namespace: "{{ .namespace }}" + {{- end }} + {{- end }} + + {{- else }} + policyRefs: + - from: + name: "{{ include "pod-identity.fullname" . }}" + {{- end }} + + {{- if .Values.podIdentityRole.inlinePolicies }} + inlinePolicies: + {{ .Values.podIdentityRole.inlinePolicies | toYaml | nindent 4 }} + {{- end }} + + {{- if .Values.podIdentityRole.tags }} + tags: + {{ .Values.podIdentityRole.tags | toYaml | nindent 4 }} + {{- end }} +{{- end }} diff --git a/charts/pod-identity/values.yaml b/charts/pod-identity/values.yaml new file mode 100644 index 0000000..0a29e19 --- /dev/null +++ b/charts/pod-identity/values.yaml @@ -0,0 +1,61 @@ +# region: us-west-2 +# accountId: "471112582304" +# create: true +# podIdentityPolicyCreate: false +# podIdentityRole: +# description: "Test" +# # Only one of the two can be true Managed Policy or Policy Refs +# # If Policy is created it will automaticaly add it on managed Policies or PolicyRefs +# managedPolicies: +# - "arn:aws:iam::aws:policy/AmazonSSMReadOnlyAccess" +# - "arn:aws:iam::aws:policy/Admin" +# policyRefs: +# - name: "custom-policy-1" +# namespace: kube-system +# - name: "AmazonSSMReadOnlyAccess" +# namespace: kube-system +# podIdentityAssociation: +# clusterName: hub-cluster +# namespace: default +# serviceAccounts: +# - serviceAccount1 +# - serviceAccount2 +# podIdentityPolicy: +# description: "Test" +# policies: +# - resourceType: ssm +# resourceName: "*" +# actions: +# - "ssm:DescribeParameters" +# - resourceType: ssm +# resourceName: parameter/* +# actions: +# - "ssm:GetParameter" +# - "ssm:GetParameters" +# - resourceType: secretsmanager +# resourceName: secret:* +# actions: +# - "secretsmanager:GetResourcePolicy" +# - "secretsmanager:GetSecretValue" +# - "secretsmanager:DescribeSecret" +# - "secretsmanager:ListSecretVersionIds" +# - "secretsmanager:CreateSecret" +# - "secretsmanager:PutSecretValue" +# - "secretsmanager:TagResource" +# - resourceType: secretsmanager +# resourceName: secret:* +# actions: +# - "secretsmanager:DeleteSecret" +# conditions: +# - test: "StringEquals" +# variable: "secretsmanager:ResourceTag/managed-by" +# values: +# - "external-secrets" +# - resourceType: kms +# resourceName: "key/*" +# actions: +# - "kms:Decrypt" +# - resourceType: ecr +# resourceName: "*" +# actions: +# - "ecr:GetAuthorizationToken"