diff --git a/.ci/pipeline_definitions b/.ci/pipeline_definitions index 25fce5cd4..f1683fcab 100644 --- a/.ci/pipeline_definitions +++ b/.ci/pipeline_definitions @@ -15,6 +15,11 @@ gardener-extension-networking-cilium: image: 'eu.gcr.io/gardener-project/gardener/extensions/networking-cilium' dockerfile: 'Dockerfile' target: gardener-extension-networking-cilium + gardener-extension-admission-cilium: + registry: 'gcr-readwrite' + image: 'eu.gcr.io/gardener-project/gardener/extensions/admission-cilium' + dockerfile: 'Dockerfile' + target: gardener-extension-admission-cilium jobs: head-update: traits: @@ -47,3 +52,5 @@ gardener-extension-networking-cilium: dockerimages: gardener-extension-networking-cilium: tag_as_latest: true + gardener-extension-admission-cilium: + tag_as_latest: true diff --git a/Dockerfile b/Dockerfile index f3a2764d5..e0c5c9074 100644 --- a/Dockerfile +++ b/Dockerfile @@ -12,3 +12,10 @@ WORKDIR / COPY charts /charts COPY --from=builder /go/bin/gardener-extension-networking-cilium /gardener-extension-networking-cilium ENTRYPOINT ["/gardener-extension-networking-cilium"] + +############# gardener-extension-admission-cilium +FROM gcr.io/distroless/static-debian11:nonroot AS gardener-extension-admission-cilium +WORKDIR / + +COPY --from=builder /go/bin/gardener-extension-admission-cilium /gardener-extension-admission-cilium +ENTRYPOINT ["/gardener-extension-admission-cilium"] diff --git a/Makefile b/Makefile index 7776ab6c5..028d821d6 100644 --- a/Makefile +++ b/Makefile @@ -14,6 +14,7 @@ EXTENSION_PREFIX := gardener-extension NAME := networking-cilium +ADMISSION_NAME := admission-cilium REGISTRY := eu.gcr.io/gardener-project/gardener IMAGE_PREFIX := $(REGISTRY)/extensions REPO_ROOT := $(shell dirname $(realpath $(lastword $(MAKEFILE_LIST)))) @@ -45,6 +46,16 @@ start: --config-file=./example/00-componentconfig.yaml \ --gardener-version="v1.39.0" +.PHONY: start-admission +start-admission: + @LEADER_ELECTION_NAMESPACE=garden GO111MODULE=on go run \ + -mod=vendor \ + -ldflags $(LD_FLAGS) \ + ./cmd/$(EXTENSION_PREFIX)-$(ADMISSION_NAME) \ + --webhook-config-server-host=0.0.0.0 \ + --webhook-config-server-port=9443 \ + --webhook-config-cert-dir=./example/admission-cilium-certs + ################################################################# # Rules related to binary build, Docker image build and release # ################################################################# @@ -60,7 +71,8 @@ docker-login: .PHONY: docker-images docker-images: - @docker build -t $(IMAGE_PREFIX)/$(NAME):$(VERSION) -t $(IMAGE_PREFIX)/$(NAME):latest -f Dockerfile -m 6g --target $(EXTENSION_PREFIX)-$(NAME) . + @docker build -t $(IMAGE_PREFIX)/$(NAME):$(VERSION) -t $(IMAGE_PREFIX)/$(NAME):latest -f Dockerfile -m 6g --target $(EXTENSION_PREFIX)-$(NAME) . + @docker build -t $(IMAGE_PREFIX)/$(ADMISSION_NAME):$(VERSION) -t $(IMAGE_PREFIX)/$(ADMISSION_NAME):latest -f Dockerfile -m 6g --target $(EXTENSION_PREFIX)-$(ADMISSION_NAME) . ##################################################################### # Rules for verification, formatting, linting, testing and cleaning # diff --git a/charts/gardener-extension-admission-cilium/.helmignore b/charts/gardener-extension-admission-cilium/.helmignore new file mode 100644 index 000000000..50af03172 --- /dev/null +++ b/charts/gardener-extension-admission-cilium/.helmignore @@ -0,0 +1,22 @@ +# 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 +*~ +# Various IDEs +.project +.idea/ +*.tmproj +.vscode/ diff --git a/charts/gardener-extension-admission-cilium/Chart.yaml b/charts/gardener-extension-admission-cilium/Chart.yaml new file mode 100644 index 000000000..f91de5865 --- /dev/null +++ b/charts/gardener-extension-admission-cilium/Chart.yaml @@ -0,0 +1,5 @@ +apiVersion: v1 +appVersion: "1.0" +description: A Helm chart for the Gardener Cilium admission controller +name: gardener-extension-admission-cilium +version: 0.1.0 diff --git a/charts/gardener-extension-admission-cilium/charts/application/Chart.yaml b/charts/gardener-extension-admission-cilium/charts/application/Chart.yaml new file mode 100644 index 000000000..a8e1b699b --- /dev/null +++ b/charts/gardener-extension-admission-cilium/charts/application/Chart.yaml @@ -0,0 +1,5 @@ +apiVersion: v1 +appVersion: "1.0" +description: A Helm chart to deploy the gardener-extension-admission-cilium application related resources +name: application +version: 0.1.0 \ No newline at end of file diff --git a/charts/gardener-extension-admission-cilium/charts/application/templates/_helpers.tpl b/charts/gardener-extension-admission-cilium/charts/application/templates/_helpers.tpl new file mode 100644 index 000000000..ab354407f --- /dev/null +++ b/charts/gardener-extension-admission-cilium/charts/application/templates/_helpers.tpl @@ -0,0 +1,27 @@ +{{- define "name" -}} +gardener-extension-admission-cilium +{{- end -}} + +{{- define "labels.app.key" -}} +app.kubernetes.io/name +{{- end -}} +{{- define "labels.app.value" -}} +{{ include "name" . }} +{{- end -}} + +{{- define "labels" -}} +{{ include "labels.app.key" . }}: {{ include "labels.app.value" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +{{- end -}} + +{{- define "image" -}} + {{- if hasPrefix "sha256:" .tag }} + {{- printf "%s@%s" .repository .tag }} + {{- else }} + {{- printf "%s:%s" .repository .tag }} + {{- end }} +{{- end }} + +{{- define "deploymentversion" -}} +apps/v1 +{{- end -}} diff --git a/charts/gardener-extension-admission-cilium/charts/application/templates/mutatingwebhook-mutator.yaml b/charts/gardener-extension-admission-cilium/charts/application/templates/mutatingwebhook-mutator.yaml new file mode 100644 index 000000000..b6b0d929b --- /dev/null +++ b/charts/gardener-extension-admission-cilium/charts/application/templates/mutatingwebhook-mutator.yaml @@ -0,0 +1,37 @@ +apiVersion: admissionregistration.k8s.io/v1 +kind: MutatingWebhookConfiguration +metadata: + name: {{ include "name" . }} +webhooks: +- name: mutation.cilium.networking.extensions.gardener.cloud + rules: + - apiGroups: + - "core.gardener.cloud" + apiVersions: + - v1alpha1 + - v1beta1 + operations: + - CREATE + resources: + - shoots + failurePolicy: Fail + objectSelector: + {{- if .Values.global.webhookConfig.useObjectSelector }} + matchLabels: + networking.extensions.gardener.cloud/cilium: "true" + {{- end }} + namespaceSelector: {} + sideEffects: None + admissionReviewVersions: + - v1 + - v1beta1 + clientConfig: + {{- if .Values.global.virtualGarden.enabled }} + url: {{ printf "https://%s.%s/webhooks/mutate" (include "name" .) (.Release.Namespace) }} + {{- else }} + service: + namespace: {{ .Release.Namespace }} + name: {{ include "name" . }} + path: /webhooks/mutate + {{- end }} + caBundle: {{ required ".Values.global.webhookConfig.caBundle is required" .Values.global.webhookConfig.caBundle | b64enc }} diff --git a/charts/gardener-extension-admission-cilium/charts/application/templates/rbac.yaml b/charts/gardener-extension-admission-cilium/charts/application/templates/rbac.yaml new file mode 100644 index 000000000..fc46f9466 --- /dev/null +++ b/charts/gardener-extension-admission-cilium/charts/application/templates/rbac.yaml @@ -0,0 +1,37 @@ +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: {{ include "name" . }} + labels: +{{ include "labels" . | indent 4 }} +rules: +- apiGroups: + - core.gardener.cloud + resources: + - shoots + verbs: + - get + - list + - watch +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: {{ include "name" . }} + labels: +{{ include "labels" . | indent 4 }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: {{ include "name" . }} +subjects: +{{- if and .Values.global.virtualGarden.enabled .Values.global.virtualGarden.user.name }} +- apiGroup: rbac.authorization.k8s.io + kind: User + name: {{ .Values.global.virtualGarden.user.name }} +{{- else }} +- kind: ServiceAccount + name: {{ include "name" . }} + namespace: {{ .Release.Namespace }} +{{- end }} diff --git a/charts/gardener-extension-admission-cilium/charts/application/templates/serviceaccount.yaml b/charts/gardener-extension-admission-cilium/charts/application/templates/serviceaccount.yaml new file mode 100644 index 000000000..3d7d77ffb --- /dev/null +++ b/charts/gardener-extension-admission-cilium/charts/application/templates/serviceaccount.yaml @@ -0,0 +1,9 @@ +{{- if and .Values.global.virtualGarden.enabled ( not .Values.global.virtualGarden.user.name ) }} +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ include "name" . }} + namespace: {{ .Release.Namespace }} + labels: +{{ include "labels" . | indent 4 }} +{{- end }} diff --git a/charts/gardener-extension-admission-cilium/charts/application/values.yaml b/charts/gardener-extension-admission-cilium/charts/application/values.yaml new file mode 120000 index 000000000..ef36be5f3 --- /dev/null +++ b/charts/gardener-extension-admission-cilium/charts/application/values.yaml @@ -0,0 +1 @@ +../../values.yaml \ No newline at end of file diff --git a/charts/gardener-extension-admission-cilium/charts/runtime/Chart.yaml b/charts/gardener-extension-admission-cilium/charts/runtime/Chart.yaml new file mode 100644 index 000000000..0fa8bcccb --- /dev/null +++ b/charts/gardener-extension-admission-cilium/charts/runtime/Chart.yaml @@ -0,0 +1,5 @@ +apiVersion: v1 +appVersion: "1.0" +description: A Helm chart to deploy the gardener-extension-admission-cilium runtime related resources +name: runtime +version: 0.1.0 \ No newline at end of file diff --git a/charts/gardener-extension-admission-cilium/charts/runtime/templates/_helpers.tpl b/charts/gardener-extension-admission-cilium/charts/runtime/templates/_helpers.tpl new file mode 100644 index 000000000..ab354407f --- /dev/null +++ b/charts/gardener-extension-admission-cilium/charts/runtime/templates/_helpers.tpl @@ -0,0 +1,27 @@ +{{- define "name" -}} +gardener-extension-admission-cilium +{{- end -}} + +{{- define "labels.app.key" -}} +app.kubernetes.io/name +{{- end -}} +{{- define "labels.app.value" -}} +{{ include "name" . }} +{{- end -}} + +{{- define "labels" -}} +{{ include "labels.app.key" . }}: {{ include "labels.app.value" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +{{- end -}} + +{{- define "image" -}} + {{- if hasPrefix "sha256:" .tag }} + {{- printf "%s@%s" .repository .tag }} + {{- else }} + {{- printf "%s:%s" .repository .tag }} + {{- end }} +{{- end }} + +{{- define "deploymentversion" -}} +apps/v1 +{{- end -}} diff --git a/charts/gardener-extension-admission-cilium/charts/runtime/templates/deplyoment.yaml b/charts/gardener-extension-admission-cilium/charts/runtime/templates/deplyoment.yaml new file mode 100644 index 000000000..93a31e208 --- /dev/null +++ b/charts/gardener-extension-admission-cilium/charts/runtime/templates/deplyoment.yaml @@ -0,0 +1,106 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ include "name" . }} + namespace: {{ .Release.Namespace }} + labels: +{{ include "labels" . | indent 4 }} +spec: + revisionHistoryLimit: 5 + replicas: {{ .Values.global.replicaCount }} + selector: + matchLabels: +{{ include "labels" . | indent 6 }} + template: + metadata: + annotations: + checksum/secret-gardener-extension-admission-cilium-cert: {{ include (print $.Template.BasePath "/secret-cert.yaml") . | sha256sum }} + {{- if .Values.global.kubeconfig }} + checksum/gardener-extension-admission-cilium-kubeconfig: {{ include (print $.Template.BasePath "/secret-kubeconfig.yaml") . | sha256sum }} + {{- end }} + labels: +{{ include "labels" . | indent 8 }} + spec: + {{- if not .Values.global.virtualGarden.enabled }} + serviceAccountName: {{ include "name" . }} + {{- else if and .Values.global.virtualGarden.enabled .Values.global.virtualGarden.user.name }} + {{- if .Values.global.serviceAccountTokenVolumeProjection.enabled }} + serviceAccountName: {{ include "name" . }} + {{- else }} + serviceAccountName: default + {{- end }} + {{- else }} + serviceAccountName: default + {{- end }} + {{- if .Values.global.kubeconfig }} + automountServiceAccountToken: false + {{- end }} + containers: + - name: {{ include "name" . }} + image: {{ include "image" .Values.global.image }} + imagePullPolicy: {{ .Values.global.image.pullPolicy }} + command: + - /gardener-extension-admission-cilium + - --webhook-config-server-port={{ .Values.global.webhookConfig.serverPort }} + - --webhook-config-cert-dir=/etc/gardener-extension-admission-cilium/srv + {{- if .Values.global.kubeconfig }} + - --kubeconfig=/etc/gardener-extension-admission-cilium/kubeconfig/kubeconfig + {{- end }} + - --health-bind-address=:{{ .Values.global.healthPort }} + ports: + - name: webhook-server + containerPort: {{ .Values.global.webhookConfig.serverPort }} + protocol: TCP + livenessProbe: + httpGet: + path: /healthz + port: {{ .Values.global.healthPort }} + scheme: HTTP + initialDelaySeconds: 5 + periodSeconds: 10 + readinessProbe: + httpGet: + path: /readyz + port: {{ .Values.global.healthPort }} + scheme: HTTP + initialDelaySeconds: 5 +{{- if .Values.global.resources }} + resources: +{{ toYaml .Values.global.resources | nindent 10 }} +{{- end }} + volumeMounts: + - name: gardener-extension-admission-cilium-cert + mountPath: /etc/gardener-extension-admission-cilium/srv + readOnly: true + {{- if .Values.global.kubeconfig }} + - name: gardener-extension-admission-cilium-kubeconfig + mountPath: /etc/gardener-extension-admission-cilium/kubeconfig + readOnly: true + {{- end }} + {{- if .Values.global.serviceAccountTokenVolumeProjection.enabled }} + - name: service-account-token + mountPath: /var/run/secrets/projected/serviceaccount + readOnly: true + {{- end }} + volumes: + - name: gardener-extension-admission-cilium-cert + secret: + secretName: gardener-extension-admission-cilium-cert + defaultMode: 420 + {{- if .Values.global.kubeconfig }} + - name: gardener-extension-admission-cilium-kubeconfig + secret: + secretName: gardener-extension-admission-cilium-kubeconfig + defaultMode: 420 + {{- end }} + {{- if .Values.global.serviceAccountTokenVolumeProjection.enabled }} + - name: service-account-token + projected: + sources: + - serviceAccountToken: + path: token + expirationSeconds: {{ .Values.global.serviceAccountTokenVolumeProjection.expirationSeconds }} + {{- if .Values.global.serviceAccountTokenVolumeProjection.audience }} + audience: {{ .Values.global.serviceAccountTokenVolumeProjection.audience }} + {{- end }} + {{- end }} diff --git a/charts/gardener-extension-admission-cilium/charts/runtime/templates/poddisruptionbudget.yaml b/charts/gardener-extension-admission-cilium/charts/runtime/templates/poddisruptionbudget.yaml new file mode 100644 index 000000000..d07ece477 --- /dev/null +++ b/charts/gardener-extension-admission-cilium/charts/runtime/templates/poddisruptionbudget.yaml @@ -0,0 +1,14 @@ +{{- if gt (int .Values.global.replicaCount) 1 }} +apiVersion: policy/v1beta1 +kind: PodDisruptionBudget +metadata: + name: {{ include "name" . }} + namespace: {{ .Release.Namespace }} + labels: +{{ include "labels" . | indent 4 }} +spec: + maxUnavailable: {{ sub (int .Values.global.replicaCount) 1 }} + selector: + matchLabels: +{{ include "labels" . | indent 6 }} +{{- end }} diff --git a/charts/gardener-extension-admission-cilium/charts/runtime/templates/secret-cert.yaml b/charts/gardener-extension-admission-cilium/charts/runtime/templates/secret-cert.yaml new file mode 100644 index 000000000..0627aca54 --- /dev/null +++ b/charts/gardener-extension-admission-cilium/charts/runtime/templates/secret-cert.yaml @@ -0,0 +1,15 @@ +apiVersion: v1 +kind: Secret +metadata: + name: gardener-extension-admission-cilium-cert + namespace: {{ .Release.Namespace }} + labels: + app: gardener + role: controller-manager + chart: "{{ .Chart.Name }}-{{ .Chart.Version }}" + release: "{{ .Release.Name }}" + heritage: "{{ .Release.Service }}" +type: Opaque +data: + tls.crt: {{ required ".Values.global.webhookConfig.tls.crt is required" (b64enc .Values.global.webhookConfig.tls.crt) }} + tls.key: {{ required ".Values.global.webhookConfig.tls.key is required" (b64enc .Values.global.webhookConfig.tls.key) }} diff --git a/charts/gardener-extension-admission-cilium/charts/runtime/templates/secret-kubeconfig.yaml b/charts/gardener-extension-admission-cilium/charts/runtime/templates/secret-kubeconfig.yaml new file mode 100644 index 000000000..36d1b380d --- /dev/null +++ b/charts/gardener-extension-admission-cilium/charts/runtime/templates/secret-kubeconfig.yaml @@ -0,0 +1,14 @@ +{{- if .Values.global.kubeconfig }} +apiVersion: v1 +kind: Secret +metadata: + name: gardener-extension-admission-cilium-kubeconfig + namespace: "{{ .Release.Namespace }}" + labels: + chart: "{{ .Chart.Name }}-{{ .Chart.Version }}" + release: "{{ .Release.Name }}" + heritage: "{{ .Release.Service }}" +type: Opaque +data: + kubeconfig: {{ .Values.global.kubeconfig | b64enc }} +{{- end }} diff --git a/charts/gardener-extension-admission-cilium/charts/runtime/templates/service.yaml b/charts/gardener-extension-admission-cilium/charts/runtime/templates/service.yaml new file mode 100644 index 000000000..fd76ba721 --- /dev/null +++ b/charts/gardener-extension-admission-cilium/charts/runtime/templates/service.yaml @@ -0,0 +1,15 @@ +apiVersion: v1 +kind: Service +metadata: + name: {{ include "name" . }} + namespace: {{ .Release.Namespace }} + labels: +{{ include "labels" . | indent 4 }} +spec: + type: ClusterIP + selector: +{{ include "labels" . | indent 4 }} + ports: + - port: 443 + protocol: TCP + targetPort: {{ .Values.global.webhookConfig.serverPort }} diff --git a/charts/gardener-extension-admission-cilium/charts/runtime/templates/serviceaccount.yaml b/charts/gardener-extension-admission-cilium/charts/runtime/templates/serviceaccount.yaml new file mode 100644 index 000000000..5c2ef7b23 --- /dev/null +++ b/charts/gardener-extension-admission-cilium/charts/runtime/templates/serviceaccount.yaml @@ -0,0 +1,19 @@ +{{- if not .Values.global.virtualGarden.enabled }} +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ include "name" . }} + namespace: {{ .Release.Namespace }} + labels: +{{ include "labels" . | indent 4 }} +{{- else if and .Values.global.virtualGarden.enabled .Values.global.virtualGarden.user.name }} +{{- if .Values.global.serviceAccountTokenVolumeProjection.enabled }} +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ include "name" . }} + namespace: {{ .Release.Namespace }} + labels: +{{ include "labels" . | indent 4 }} +{{- end }} +{{- end }} diff --git a/charts/gardener-extension-admission-cilium/charts/runtime/templates/vpa.yaml b/charts/gardener-extension-admission-cilium/charts/runtime/templates/vpa.yaml new file mode 100644 index 000000000..8fcc1ad74 --- /dev/null +++ b/charts/gardener-extension-admission-cilium/charts/runtime/templates/vpa.yaml @@ -0,0 +1,29 @@ +{{- if .Values.global.vpa.enabled}} +apiVersion: "autoscaling.k8s.io/v1" +kind: VerticalPodAutoscaler +metadata: + name: {{ include "name" . }}-vpa + namespace: {{ .Release.Namespace }} +spec: + {{- if .Values.global.vpa.resourcePolicy }} + resourcePolicy: + containerPolicies: + - containerName: '*' + {{- if .Values.global.vpa.resourcePolicy.minAllowed }} + minAllowed: + cpu: {{ required ".Values.global.vpa.resourcePolicy.minAllowed.cpu is required" .Values.global.vpa.resourcePolicy.minAllowed.cpu }} + memory: {{ required ".Values.global.vpa.resourcePolicy.minAllowed.memory is required" .Values.global.vpa.resourcePolicy.minAllowed.memory }} + {{- end }} + {{- if .Values.global.vpa.resourcePolicy.maxAllowed }} + maxAllowed: + cpu: {{ required ".Values.global.vpa.resourcePolicy.maxAllowed.cpu is required" .Values.global.vpa.resourcePolicy.maxAllowed.cpu }} + memory: {{ required ".Values.global.vpa.resourcePolicy.maxAllowed.memory is required" .Values.global.vpa.resourcePolicy.maxAllowed.memory }} + {{- end }} + {{- end }} + targetRef: + apiVersion: apps/v1 + kind: Deployment + name: {{ include "name" . }} + updatePolicy: + updateMode: {{ .Values.global.vpa.updatePolicy.updateMode }} +{{- end }} diff --git a/charts/gardener-extension-admission-cilium/charts/runtime/values.yaml b/charts/gardener-extension-admission-cilium/charts/runtime/values.yaml new file mode 120000 index 000000000..ef36be5f3 --- /dev/null +++ b/charts/gardener-extension-admission-cilium/charts/runtime/values.yaml @@ -0,0 +1 @@ +../../values.yaml \ No newline at end of file diff --git a/charts/gardener-extension-admission-cilium/templates/_helpers.tpl b/charts/gardener-extension-admission-cilium/templates/_helpers.tpl new file mode 100644 index 000000000..ab354407f --- /dev/null +++ b/charts/gardener-extension-admission-cilium/templates/_helpers.tpl @@ -0,0 +1,27 @@ +{{- define "name" -}} +gardener-extension-admission-cilium +{{- end -}} + +{{- define "labels.app.key" -}} +app.kubernetes.io/name +{{- end -}} +{{- define "labels.app.value" -}} +{{ include "name" . }} +{{- end -}} + +{{- define "labels" -}} +{{ include "labels.app.key" . }}: {{ include "labels.app.value" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +{{- end -}} + +{{- define "image" -}} + {{- if hasPrefix "sha256:" .tag }} + {{- printf "%s@%s" .repository .tag }} + {{- else }} + {{- printf "%s:%s" .repository .tag }} + {{- end }} +{{- end }} + +{{- define "deploymentversion" -}} +apps/v1 +{{- end -}} diff --git a/charts/gardener-extension-admission-cilium/values.yaml b/charts/gardener-extension-admission-cilium/values.yaml new file mode 100644 index 000000000..d464495ef --- /dev/null +++ b/charts/gardener-extension-admission-cilium/values.yaml @@ -0,0 +1,47 @@ +global: + virtualGarden: + enabled: false + user: + name: "" + image: + repository: eu.gcr.io/gardener-project/gardener/extensions/admission-cilium + tag: latest + pullPolicy: IfNotPresent + replicaCount: 1 + resources: {} + healthPort: 8081 + vpa: + enabled: true + resourcePolicy: + minAllowed: + cpu: 50m + memory: 64Mi + maxAllowed: + cpu: 4 + memory: 10G + updatePolicy: + updateMode: "Auto" + webhookConfig: + caBundle: | + -----BEGIN CERTIFICATE----- + ... + -----END CERTIFICATE----- + serverPort: 10250 + tls: + crt: | + -----BEGIN CERTIFICATE----- + ... + -----END CERTIFICATE----- + key: | + -----BEGIN RSA PRIVATE KEY----- + ... + -----END RSA PRIVATE KEY----- + # Please make sure you are running `gardener@v1.42` or later before setting this to true. + useObjectSelector: false + # Kubeconfig to the target cluster. In-cluster configuration will be used if not specified. + kubeconfig: + + serviceAccountTokenVolumeProjection: + enabled: false + expirationSeconds: 43200 + audience: "" diff --git a/cmd/gardener-extension-admission-cilium/app/app.go b/cmd/gardener-extension-admission-cilium/app/app.go new file mode 100644 index 000000000..9a9f288a4 --- /dev/null +++ b/cmd/gardener-extension-admission-cilium/app/app.go @@ -0,0 +1,105 @@ +// Copyright (c) 2021 SAP SE or an SAP affiliate company. All rights reserved. This file is licensed under the Apache Software License, v. 2 except as noted otherwise in the LICENSE file +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package app + +import ( + "context" + "fmt" + + admissioncmd "github.com/gardener/gardener-extension-networking-cilium/pkg/admission/cmd" + ciliuminstall "github.com/gardener/gardener-extension-networking-cilium/pkg/apis/cilium/install" + "github.com/gardener/gardener-extension-networking-cilium/pkg/cilium" + gardenerhealthz "github.com/gardener/gardener/pkg/healthz" + + controllercmd "github.com/gardener/gardener/extensions/pkg/controller/cmd" + "github.com/gardener/gardener/extensions/pkg/util" + webhookcmd "github.com/gardener/gardener/extensions/pkg/webhook/cmd" + "github.com/gardener/gardener/pkg/apis/core/install" + "github.com/spf13/cobra" + componentbaseconfig "k8s.io/component-base/config" + "sigs.k8s.io/controller-runtime/pkg/healthz" + logf "sigs.k8s.io/controller-runtime/pkg/log" + "sigs.k8s.io/controller-runtime/pkg/manager" +) + +var log = logf.Log.WithName("gardener-extension-admission-cilium") + +// NewAdmissionCommand creates a new command for running a Cilium admission webhook. +func NewAdmissionCommand(ctx context.Context) *cobra.Command { + var ( + restOpts = &controllercmd.RESTOptions{} + mgrOpts = &controllercmd.ManagerOptions{ + WebhookServerPort: 443, + HealthBindAddress: ":8081", + } + webhookSwitches = admissioncmd.GardenWebhookSwitchOptions() + webhookOptions = webhookcmd.NewAddToManagerSimpleOptions(webhookSwitches) + + aggOption = controllercmd.NewOptionAggregator( + restOpts, + mgrOpts, + webhookOptions, + ) + ) + + cmd := &cobra.Command{ + Use: fmt.Sprintf("admission-%s", cilium.Name), + + RunE: func(cmd *cobra.Command, args []string) error { + if err := aggOption.Complete(); err != nil { + return fmt.Errorf("error completing options: %w", err) + } + util.ApplyClientConnectionConfigurationToRESTConfig(&componentbaseconfig.ClientConnectionConfiguration{ + QPS: 100.0, + Burst: 130, + }, restOpts.Completed().Config) + + mgr, err := manager.New(restOpts.Completed().Config, mgrOpts.Completed().Options()) + if err != nil { + return fmt.Errorf("could not instantiate manager: %w", err) + } + + install.Install(mgr.GetScheme()) + + if err := ciliuminstall.AddToScheme(mgr.GetScheme()); err != nil { + return fmt.Errorf("could not update manager scheme: %w", err) + } + + log.Info("Setting up webhook server") + + if err := webhookOptions.Completed().AddToManager(mgr); err != nil { + return err + } + + if err := mgr.AddReadyzCheck("informer-sync", gardenerhealthz.NewCacheSyncHealthz(mgr.GetCache())); err != nil { + return fmt.Errorf("could not add readycheck for informers: %w", err) + } + + if err := mgr.AddHealthzCheck("ping", healthz.Ping); err != nil { + return fmt.Errorf("could not add healthcheck: %w", err) + } + + if err := mgr.AddReadyzCheck("webhook-server", mgr.GetWebhookServer().StartedChecker()); err != nil { + return fmt.Errorf("could not add readycheck of webhook to manager: %w", err) + } + + return mgr.Start(ctx) + }, + } + + aggOption.AddFlags(cmd.Flags()) + + return cmd +} diff --git a/cmd/gardener-extension-admission-cilium/main.go b/cmd/gardener-extension-admission-cilium/main.go new file mode 100644 index 000000000..195142a54 --- /dev/null +++ b/cmd/gardener-extension-admission-cilium/main.go @@ -0,0 +1,32 @@ +// Copyright (c) 2021 SAP SE or an SAP affiliate company. All rights reserved. This file is licensed under the Apache Software License, v. 2 except as noted otherwise in the LICENSE file +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package main + +import ( + "github.com/gardener/gardener-extension-networking-cilium/cmd/gardener-extension-admission-cilium/app" + + "github.com/gardener/gardener/pkg/logger" + runtimelog "sigs.k8s.io/controller-runtime/pkg/log" + "sigs.k8s.io/controller-runtime/pkg/manager/signals" +) + +func main() { + runtimelog.SetLogger(logger.ZapLogger(false)) + cmd := app.NewAdmissionCommand(signals.SetupSignalHandler()) + + if err := cmd.Execute(); err != nil { + runtimelog.Log.Error(err, "Error executing the main controller command") + } +} diff --git a/example/30-mutatingwebhookconfiguration.yaml b/example/30-mutatingwebhookconfiguration.yaml new file mode 100644 index 000000000..5bb10e52c --- /dev/null +++ b/example/30-mutatingwebhookconfiguration.yaml @@ -0,0 +1,29 @@ +apiVersion: admissionregistration.k8s.io/v1 +kind: MutatingWebhookConfiguration +metadata: + name: gardener-extension-admission-cilium +webhooks: +- name: mutation.cilium.networking.extension.gardener.cloud + rules: + - apiGroups: + - "core.gardener.cloud" + apiVersions: + - v1alpha1 + - v1beta1 + operations: + - CREATE + resources: + - shoots + failurePolicy: Fail + # Please make sure you are running `gardener@v1.42` or later before enabling this object selector. + objectSelector: + matchLabels: + networking.extensions.gardener.cloud/cilium: "true" + namespaceSelector: {} + sideEffects: None + admissionReviewVersions: + - v1 + - v1beta1 + clientConfig: + url: "https://localhost:9443/webhooks/mutate" + caBundle: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUMrekNDQWVPZ0F3SUJBZ0lSQU8xZHN5dHBkNW9Jd2N3SXo2d3hpb2t3RFFZSktvWklodmNOQVFFTEJRQXcKRnpFVk1CTUdBMVVFQXhNTVoyRnlaR1Z1WlhJdFpHVjJNQjRYRFRJeE1ERXlNVEV3TXpNeU5Wb1hEVE14TURFeQpNVEV3TXpNeU5Wb3dGekVWTUJNR0ExVUVBeE1NWjJGeVpHVnVaWEl0WkdWMk1JSUJJakFOQmdrcWhraUc5dzBCCkFRRUZBQU9DQVE4QU1JSUJDZ0tDQVFFQXhYRzJ2bWQzUXNuOXhqRG1KcSszMndITHkxS2tlYkpYNERGYlBQU1cKbWFRd29XcStFUzJCVldYekdPZmRkWlVFV0RRL1BwSDg5MmtuY0JYRmdjY2pDbzNlMW5RdHBoZ2xuRFh4WnQxZwpZV0NWK3BsOXJXWENuRXdqOElKZU1aNXVDczl4Ynh2TUhUSk1LYTA4WktHSWMyUzFDZlRwVmtYNzJnZ3VoYlNhCnBaeWhkd0x3Mzl5M1BXUEdiQkdyQWdHUEpFVG9iUmc0QW96SXRaQTRVajVnYzl6c3I4RHBxdnhzUXM1UXQ5NTcKRWFUd2JQeXNobHdwaFg0eXVrZTcvbmdCeUlCTFFRZnEyZ2I1ZHRKL3BFbzR1TUNZSGlTcEpBZWExaG9ac3phSApqKzBJTjF2aENFeFFPekUvUkxGenRscTFBc2s5VlR5WjZIektaakpLNExMVHNRSURBUUFCbzBJd1FEQU9CZ05WCkhROEJBZjhFQkFNQ0FhWXdEd1lEVlIwVEFRSC9CQVV3QXdFQi96QWRCZ05WSFE0RUZnUVVZdTltMEFMSWx6Q04KNVNibGJNcWYxUW5Rdjlvd0RRWUpLb1pJaHZjTkFRRUxCUUFEZ2dFQkFCSkVEdmk2STdpZ1VnUjg3TnVnLzVGaAo1TlFaZnMwbGFZQ05RK2NDNU1qMXpDeUdudjQ0ZlZRbFhleFBYWUREcmEyUHlyWGdWeWNGRE5vWmYvSDJGOWViCm9IVnYwWWhwL0FWTGVXdHVJSnh5d3IrYVFGT0tQY3oxNFROQTRGUmhoY0U0RjlqYytUN1lwZEJLMTRLK0UwZWUKbnhaQW44QlYrNkt2cUZteUJmU3pQSXROdGJjS2MxdzVnSlZ3Mk5OMWRocFFrQ0NNbHpHOTE0d2tPSExTUnVQTwpCTk5yMWtnQXVoMUpnZ2h6Yzdia2xPQ3dxQzZKeThOQkZQQ211L2hEb0d0US9mc3lEV0Jvb0J3enIzTlZ4WTlsCklaM2ZvUlFtM2MvNEM1K3dmSVdLZ2t2SXErOU1KM0tTL2JlRnRSVXpZakZhekhoUEVHY1lldlI0cjZqdTZhaz0KLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQo= diff --git a/example/admission-cilium-certs/tls.crt b/example/admission-cilium-certs/tls.crt new file mode 100644 index 000000000..42d68d62c --- /dev/null +++ b/example/admission-cilium-certs/tls.crt @@ -0,0 +1,24 @@ +-----BEGIN CERTIFICATE----- +MIIEDjCCAvagAwIBAgIQSVslL6snUERyyaSFm24m8DANBgkqhkiG9w0BAQsFADAX +MRUwEwYDVQQDEwxnYXJkZW5lci1kZXYwHhcNMjEwMTIxMTAzMzI1WhcNMzEwMTIx +MTAzMzI1WjAUMRIwEAYDVQQDEwlsb2NhbGhvc3QwggEiMA0GCSqGSIb3DQEBAQUA +A4IBDwAwggEKAoIBAQDbmoQZev18qHantgjlicpgYNScMFxJxbAhKQIc2b4OfIYm +hNdO9MkSWmk4PzTNbwGwSZR9q7uAyFlb/urt7/bOYDyBB1GrXom4nR/8Cg/korQT +GF/tjS64hhNHHbtJ+2z6yWUgSpCaogH8Z/VqnfUUp/iTeaz0LI1v1vLExk1MMWWj +FLueQgboQwVpNpsH3k7MCeg40Nc/eOsFdOKpOS545OaTM+ii7fNpyQ6bCdoRNHvL +5genZwXjpRu9EKr7C2rRoQ4lHCU2Rrr+mHT2J5SXFHy7r/zBWT20h8/LvFB/wDr5 +wHYJ650RrvErpMjXkblharoZCDNVdy6x0g17cEZBAgMBAAGjggFXMIIBUzAOBgNV +HQ8BAf8EBAMCBaAwEwYDVR0lBAwwCgYIKwYBBQUHAwEwDAYDVR0TAQH/BAIwADCC +ARwGA1UdEQSCARMwggEPgglsb2NhbGhvc3SCFGhvc3QuZG9ja2VyLmludGVybmFs +giBnYXJkZW5lci1leHRlbnNpb24tYWRtaXNzaW9uLWF3c4InZ2FyZGVuZXItZXh0 +ZW5zaW9uLWFkbWlzc2lvbi1hd3MuZ2FyZGVugitnYXJkZW5lci1leHRlbnNpb24t +YWRtaXNzaW9uLWF3cy5nYXJkZW4uc3ZjgjNnYXJkZW5lci1leHRlbnNpb24tYWRt +aXNzaW9uLWF3cy5nYXJkZW4uc3ZjLmNsdXN0ZXKCOWdhcmRlbmVyLWV4dGVuc2lv +bi1hZG1pc3Npb24tYXdzLmdhcmRlbi5zdmMuY2x1c3Rlci5sb2NhbIcEfwAAATAN +BgkqhkiG9w0BAQsFAAOCAQEANsJ+QEApmxTirtK8kFbuXqkSaBU6Qgs6Hw5IAjbJ +mz6fjM5z6fstGRhzm0OVjFVM4lG0u41qM1ninE20mLlgN4iXO/qrkxu8HoZU5NWW +t1rofHZXlhn8oyRZIEZKakgeuwgG0NDB3N6wiQzpwPnSIKNekPjX1BL8N47WVUOe +UTsVvzNX/JmzgfM1ezhI4qPUTkIeJ8zS4ZioZDGHR4sUIWtVeLpPkpO9LJq31+J5 +ok0Rw28EilMVb3Oi0I2zfqWaWSIWqlnXkzrmmUT7s8s4wJHgepUNuazZjx+1SlhJ +RuUvpCQB5HjceJDfI7OtdYi6YuH7sY7jXSD++aPBuXvQ/A== +-----END CERTIFICATE----- diff --git a/example/admission-cilium-certs/tls.key b/example/admission-cilium-certs/tls.key new file mode 100644 index 000000000..ce024f384 --- /dev/null +++ b/example/admission-cilium-certs/tls.key @@ -0,0 +1,27 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEogIBAAKCAQEA25qEGXr9fKh2p7YI5YnKYGDUnDBcScWwISkCHNm+DnyGJoTX +TvTJElppOD80zW8BsEmUfau7gMhZW/7q7e/2zmA8gQdRq16JuJ0f/AoP5KK0Exhf +7Y0uuIYTRx27Sfts+sllIEqQmqIB/Gf1ap31FKf4k3ms9CyNb9byxMZNTDFloxS7 +nkIG6EMFaTabB95OzAnoONDXP3jrBXTiqTkueOTmkzPoou3zackOmwnaETR7y+YH +p2cF46UbvRCq+wtq0aEOJRwlNka6/ph09ieUlxR8u6/8wVk9tIfPy7xQf8A6+cB2 +CeudEa7xK6TI15G5YWq6GQgzVXcusdINe3BGQQIDAQABAoIBAEiyQu6ob0eYAQeN +1C4gShVTmK5HuBVX0vF3QNLKJgdno4UWzqu9jt57fX94NQOYrsdr5DMh6YU9TY+N +uLmhiWNSKlVQVfHT7uVlZlQqBI7caZ40oHTkGsZM5A7Twc9A4xe2Gbrx1CLMZLno +tC5iMeJvpHM1gVKneP6/+ke3mZkR1/+NoFnNebJ7fDcmluhd1f9oqAR0SpxgTzt6 +oKAiCQnWCbReC2ructNsYOSam6qahaGZbsXxHKY3cicYXJEHJ6qN+xKy4shme4+v +McxTrB9exNoTiJniGg5NWmo4RE5T4P+CJofjg0WxoVx4m/RWJpHiiX172wFt6Prj +K8WEEEECgYEA4s9y6VDHUae6JVBCXMXuWis3pgw6TRIviJECnLv0V+mAbtbnI4c3 +qTBZLRZ6JPQZRYYE4VQeNzyqINIwXGqwDPqhv6uzlr3i5UOf91wu2HwZANI9hPvT +HsjPh7lFyH0nt6ToxPWSC+GlC3aUqm5AJmW0nTUi8MIy6mqa1utqhjkCgYEA992h +kCKfuvm+na4JeHqjngyPGZS+Gq7c5oK52bZYF/gCi5oVPe2ihB3PmTI0HPBh2wXB +/lGuU7pv+Oq6gPsCF3rqJE4UWKvAhiM/7wQ2fY2n1N+jB0ocmDIpJsQRYDm5E7kO +zAq7fjkB/Zzfl6UPgd92BdtA/7mkH+zHb6qQAEkCgYALg5qCy64CsDAb+tIToZyz +CSSfElnXVcgB99KZIFWMLPdvKQu82v1xYln0lwKGY7nwtJgE1F9gUH0Wg3UfC+96 +CTMy5sWMLoGZP/Cb/xsFtG8UgpfK63nRQ0J90mL/hZMBmKaUcR8D6WWWimOLr2Mk +T992Z58pd8Jb8iOAK51RyQKBgCdi8n9i4RrnAKExvJOGeWVt/XdFKYg37SY786hi +z1DPuifQzjtO/Zoc2pYvYhSPJh2VpqPw+tCXOZ/GPOit+kEc6QPn3FfSwv8NruUe +OEJvNhIfj1pjLnQI1H0yfshZo808hNtrgSunh2dzfBwuwG4Uwj5f/s4kA66HA5H8 ++nDxAoGAR9c2D1EaW3GCiUsH0ZaI6QM3zNCdkdj2uW45B6DTilmw4rLxxPgUlIG1 +17x04wZi0fLxl+snRWIWf+QaqktLVIZ0aY83rmwZ0pjewK+X/VZJSn8XUo3/Bp5l +c4ADSNoBymWd+KY/fG6x3/S031V9wuIBOKEBLY+8T55K1tJSSso= +-----END RSA PRIVATE KEY----- diff --git a/go.mod b/go.mod index eb1f7a21c..c290d1cf5 100644 --- a/go.mod +++ b/go.mod @@ -18,6 +18,7 @@ require ( k8s.io/client-go v11.0.1-0.20190409021438-1a26190bd76a+incompatible k8s.io/code-generator v0.24.2 k8s.io/component-base v0.24.2 + k8s.io/utils v0.0.0-20220210201930-3a6ce19ff2f9 sigs.k8s.io/controller-runtime v0.12.1 ) @@ -134,7 +135,6 @@ require ( k8s.io/kube-aggregator v0.24.2 // indirect k8s.io/kube-openapi v0.0.0-20220328201542-3ee0da9b0b42 // indirect k8s.io/metrics v0.24.2 // indirect - k8s.io/utils v0.0.0-20220210201930-3a6ce19ff2f9 // indirect sigs.k8s.io/controller-runtime/tools/setup-envtest v0.0.0-20220613074012-11e533d55213 // indirect sigs.k8s.io/controller-tools v0.9.0 // indirect sigs.k8s.io/json v0.0.0-20211208200746-9f7c6b3444d2 // indirect diff --git a/pkg/admission/cmd/options.go b/pkg/admission/cmd/options.go new file mode 100644 index 000000000..bb98d7af2 --- /dev/null +++ b/pkg/admission/cmd/options.go @@ -0,0 +1,28 @@ +// Copyright (c) 2021 SAP SE or an SAP affiliate company. All rights reserved. This file is licensed under the Apache Software License, v. 2 except as noted otherwise in the LICENSE file +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package cmd + +import ( + webhookcmd "github.com/gardener/gardener/extensions/pkg/webhook/cmd" + + "github.com/gardener/gardener-extension-networking-cilium/pkg/admission/mutator" +) + +// GardenWebhookSwitchOptions are the webhookcmd.SwitchOptions for the admission webhooks. +func GardenWebhookSwitchOptions() *webhookcmd.SwitchOptions { + return webhookcmd.NewSwitchOptions( + webhookcmd.Switch(mutator.Name, mutator.New), + ) +} diff --git a/pkg/admission/mutator/shoot.go b/pkg/admission/mutator/shoot.go new file mode 100644 index 000000000..092b8addc --- /dev/null +++ b/pkg/admission/mutator/shoot.go @@ -0,0 +1,53 @@ +// Copyright (c) 2021 SAP SE or an SAP affiliate company. All rights reserved. This file is licensed under the Apache Software License, v. 2 except as noted otherwise in the LICENSE file +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package mutator + +import ( + "context" + "fmt" + + extensionswebhook "github.com/gardener/gardener/extensions/pkg/webhook" + gardencorev1beta1 "github.com/gardener/gardener/pkg/apis/core/v1beta1" + + "k8s.io/utils/pointer" + "sigs.k8s.io/controller-runtime/pkg/client" +) + +// NewShootMutator returns a new instance of a shoot mutator. +func NewShootMutator() extensionswebhook.Mutator { + return &shoot{} +} + +type shoot struct{} + +// Mutate mutates the given shoot object. +func (s *shoot) Mutate(ctx context.Context, new, old client.Object) error { + shoot, ok := new.(*gardencorev1beta1.Shoot) + if !ok { + return fmt.Errorf("wrong object type %T", new) + } + + if old != nil { + // Leave existing clusters as is + return nil + } + + if shoot.Spec.Kubernetes.KubeProxy == nil { + shoot.Spec.Kubernetes.KubeProxy = &gardencorev1beta1.KubeProxyConfig{} + } + shoot.Spec.Kubernetes.KubeProxy.Enabled = pointer.Bool(false) + + return nil +} diff --git a/pkg/admission/mutator/webhook.go b/pkg/admission/mutator/webhook.go new file mode 100644 index 000000000..f5ec48a48 --- /dev/null +++ b/pkg/admission/mutator/webhook.go @@ -0,0 +1,80 @@ +// Copyright (c) 2021 SAP SE or an SAP affiliate company. All rights reserved. This file is licensed under the Apache Software License, v. 2 except as noted otherwise in the LICENSE file +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package mutator + +import ( + "github.com/gardener/gardener-extension-networking-cilium/pkg/cilium" + + extensionswebhook "github.com/gardener/gardener/extensions/pkg/webhook" + gardencorev1beta1 "github.com/gardener/gardener/pkg/apis/core/v1beta1" + + "sigs.k8s.io/controller-runtime/pkg/client" + "sigs.k8s.io/controller-runtime/pkg/event" + "sigs.k8s.io/controller-runtime/pkg/log" + "sigs.k8s.io/controller-runtime/pkg/manager" + "sigs.k8s.io/controller-runtime/pkg/predicate" +) + +const ( + // Name is a name for a validation webhook. + Name = "mutator" +) + +var logger = log.Log.WithName("cilium-validator-webhook") + +// New creates a new webhook that validates Shoot resources. +func New(mgr manager.Manager) (*extensionswebhook.Webhook, error) { + logger.Info("Setting up webhook", "name", Name) + + return extensionswebhook.New(mgr, extensionswebhook.Args{ + Provider: cilium.Name, + Name: Name, + Path: "/webhooks/mutate", + Predicates: []predicate.Predicate{createCiliumPredicate()}, + Mutators: map[extensionswebhook.Mutator][]extensionswebhook.Type{ + NewShootMutator(): {{Obj: &gardencorev1beta1.Shoot{}}}, + }, + }) +} + +func createCiliumPredicate() predicate.Funcs { + f := func(obj client.Object) bool { + if obj == nil { + return false + } + + shoot, ok := obj.(*gardencorev1beta1.Shoot) + if !ok { + return false + } + + return shoot.Spec.Networking.Type == cilium.ReleaseName + } + + return predicate.Funcs{ + CreateFunc: func(event event.CreateEvent) bool { + return f(event.Object) + }, + UpdateFunc: func(event event.UpdateEvent) bool { + return f(event.ObjectNew) + }, + GenericFunc: func(event event.GenericEvent) bool { + return f(event.Object) + }, + DeleteFunc: func(event event.DeleteEvent) bool { + return f(event.Object) + }, + } +} diff --git a/vendor/github.com/gardener/gardener/pkg/healthz/default.go b/vendor/github.com/gardener/gardener/pkg/healthz/default.go new file mode 100644 index 000000000..3af2a5c25 --- /dev/null +++ b/vendor/github.com/gardener/gardener/pkg/healthz/default.go @@ -0,0 +1,70 @@ +// Copyright (c) 2020 SAP SE or an SAP affiliate company. All rights reserved. This file is licensed under the Apache Software License, v. 2 except as noted otherwise in the LICENSE file +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package healthz + +import ( + "sync" +) + +// DefaultHealthManagerName is the name of the default health manager. +const DefaultHealthManagerName = "default" + +// NewDefaultHealthz returns a default health manager that stores the given health status and returns it. +func NewDefaultHealthz() Manager { + return &defaultHealthz{} +} + +type defaultHealthz struct { + mutex sync.RWMutex + health bool + started bool +} + +// Name returns the name of the health manager. +func (d *defaultHealthz) Name() string { + return DefaultHealthManagerName +} + +// Start starts the health manager. +func (d *defaultHealthz) Start() { + d.mutex.Lock() + defer d.mutex.Unlock() + + d.started = true + d.health = true +} + +// Stop stops the health manager. +func (d *defaultHealthz) Stop() { + d.mutex.Lock() + defer d.mutex.Unlock() + + d.started = false + d.health = false +} + +// Get returns the current health status. +func (d *defaultHealthz) Get() bool { + d.mutex.RLock() + defer d.mutex.RUnlock() + return d.health +} + +// Set sets the current health status. +func (d *defaultHealthz) Set(health bool) { + d.mutex.Lock() + defer d.mutex.Unlock() + d.health = health && d.started +} diff --git a/vendor/github.com/gardener/gardener/pkg/healthz/healthz.go b/vendor/github.com/gardener/gardener/pkg/healthz/healthz.go new file mode 100644 index 000000000..ec984ae4a --- /dev/null +++ b/vendor/github.com/gardener/gardener/pkg/healthz/healthz.go @@ -0,0 +1,45 @@ +// Copyright (c) 2020 SAP SE or an SAP affiliate company. All rights reserved. This file is licensed under the Apache Software License, v. 2 except as noted otherwise in the LICENSE file +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package healthz + +import ( + "net/http" +) + +// Manager is an interface for health managers. +type Manager interface { + // Name returns the name of the health manager. + Name() string + // Start starts the health manager. + Start() + // Stop stops the health manager. + Stop() + // Get returns the current health status. + Get() bool + // Set updates the current health status with the given value. + Set(bool) +} + +// HandlerFunc returns a HTTP handler that responds with 200 OK status code if the given health manager returns true, +// otherwise 500 Internal Server Error status code will be returned. +func HandlerFunc(h Manager) func(w http.ResponseWriter, r *http.Request) { + return func(w http.ResponseWriter, r *http.Request) { + if !h.Get() { + w.WriteHeader(http.StatusInternalServerError) + } else { + w.WriteHeader(http.StatusOK) + } + } +} diff --git a/vendor/github.com/gardener/gardener/pkg/healthz/informer.go b/vendor/github.com/gardener/gardener/pkg/healthz/informer.go new file mode 100644 index 000000000..798ca64cc --- /dev/null +++ b/vendor/github.com/gardener/gardener/pkg/healthz/informer.go @@ -0,0 +1,42 @@ +// Copyright (c) 2021 SAP SE or an SAP affiliate company. All rights reserved. This file is licensed under the Apache Software License, v. 2 except as noted otherwise in the LICENSE file +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package healthz + +import ( + "context" + "fmt" + "net/http" + "time" + + "sigs.k8s.io/controller-runtime/pkg/healthz" +) + +type cacheSyncWaiter interface { + WaitForCacheSync(ctx context.Context) bool +} + +// NewCacheSyncHealthz returns a new healthz.Checker that will pass only if all informers in the given cacheSyncWaiter sync. +func NewCacheSyncHealthz(cacheSyncWaiter cacheSyncWaiter) healthz.Checker { + return func(_ *http.Request) error { + // cache.Cache.WaitForCacheSync is racy for closed context, so use context with 1ms timeout instead. + ctx, cancel := context.WithTimeout(context.Background(), 1*time.Millisecond) + defer cancel() + + if !cacheSyncWaiter.WaitForCacheSync(ctx) { + return fmt.Errorf("informers not synced yet") + } + return nil + } +} diff --git a/vendor/github.com/gardener/gardener/pkg/healthz/periodic.go b/vendor/github.com/gardener/gardener/pkg/healthz/periodic.go new file mode 100644 index 000000000..718986704 --- /dev/null +++ b/vendor/github.com/gardener/gardener/pkg/healthz/periodic.go @@ -0,0 +1,106 @@ +// Copyright (c) 2020 SAP SE or an SAP affiliate company. All rights reserved. This file is licensed under the Apache Software License, v. 2 except as noted otherwise in the LICENSE file +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package healthz + +import ( + "sync" + "time" + + "k8s.io/utils/clock" +) + +// PeriodicHealthManagerName is the name of the periodic health manager. +const PeriodicHealthManagerName = "periodic" + +// NewPeriodicHealthz returns a health manager that automatically sets the health status to false after the given reset +// duration. The timer is reset again when the health status is true (i.e., a running timer is reset and starts again +// from the beginning). +func NewPeriodicHealthz(clock clock.Clock, resetDuration time.Duration) Manager { + return &periodicHealthz{clock: clock, resetDuration: resetDuration} +} + +type periodicHealthz struct { + clock clock.Clock + mutex sync.RWMutex + health bool + timer clock.Timer + resetDuration time.Duration + started bool + stopCh chan struct{} +} + +// Name returns the name of the health manager. +func (p *periodicHealthz) Name() string { + return PeriodicHealthManagerName +} + +// Start starts the health manager. +func (p *periodicHealthz) Start() { + p.mutex.Lock() + defer p.mutex.Unlock() + + if p.started { + return + } + + p.health = true + p.timer = p.clock.NewTimer(p.resetDuration) + p.started = true + p.stopCh = make(chan struct{}) + + go func() { + for { + select { + case <-p.timer.C(): + p.Set(false) + case <-p.stopCh: + p.timer.Stop() + return + } + } + }() +} + +// Stop stops the health manager. +func (p *periodicHealthz) Stop() { + p.mutex.Lock() + defer p.mutex.Unlock() + + p.health = false + if !p.started { + return + } + + close(p.stopCh) + p.started = false +} + +// Get returns the current health status. +func (p *periodicHealthz) Get() bool { + p.mutex.RLock() + defer p.mutex.RUnlock() + return p.health +} + +// Set sets the current health status. When the health status is 'true' then the timer is reset. +func (p *periodicHealthz) Set(health bool) { + p.mutex.Lock() + defer p.mutex.Unlock() + p.health = health && p.started + + if health && p.started { + p.timer.Reset(p.resetDuration) + } +} diff --git a/vendor/modules.txt b/vendor/modules.txt index 9cb25e88a..c02399e60 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -128,6 +128,7 @@ github.com/gardener/gardener/pkg/controllerutils/reconciler github.com/gardener/gardener/pkg/extensions github.com/gardener/gardener/pkg/gardenlet/apis/config github.com/gardener/gardener/pkg/gardenlet/apis/config/v1alpha1 +github.com/gardener/gardener/pkg/healthz github.com/gardener/gardener/pkg/logger github.com/gardener/gardener/pkg/resourcemanager/controller/garbagecollector/references github.com/gardener/gardener/pkg/utils