Skip to content
This repository has been archived by the owner on Apr 11, 2024. It is now read-only.

Commit

Permalink
feat: deploy mutating webhook
Browse files Browse the repository at this point in the history
  • Loading branch information
dkoshkin committed Apr 10, 2024
1 parent 05b8c1a commit cba0297
Show file tree
Hide file tree
Showing 15 changed files with 358 additions and 15 deletions.
9 changes: 9 additions & 0 deletions api/v1alpha1/clusterconfig_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import (
clusterv1 "sigs.k8s.io/cluster-api/api/v1beta1"

"github.com/d2iq-labs/cluster-api-runtime-extensions-nutanix/api/openapi/patterns"
"github.com/d2iq-labs/cluster-api-runtime-extensions-nutanix/api/variables"
)

type StorageProvisioner string
Expand Down Expand Up @@ -94,6 +95,14 @@ func (s ClusterConfigSpec) VariableSchema() clusterv1.VariableSchema { //nolint:
return clusterConfigProps
}

func (s *ClusterConfigSpec) ToClusterVariable(name string) (*clusterv1.ClusterVariable, error) {
return variables.MarshalToClusterVariable(name, s)
}

func (s *ClusterConfigSpec) FromClusterVariable(clusterVariable *clusterv1.ClusterVariable) error {
return variables.UnmarshalClusterVariable(clusterVariable, s)
}

// GenericClusterConfig defines the generic cluster configdesired.
type GenericClusterConfig struct {
// +optional
Expand Down
14 changes: 12 additions & 2 deletions api/v1alpha1/node_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,16 +8,18 @@ import (

metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
clusterv1 "sigs.k8s.io/cluster-api/api/v1beta1"

"github.com/d2iq-labs/cluster-api-runtime-extensions-nutanix/api/variables"
)

//+kubebuilder:object:root=true
// +kubebuilder:object:root=true

// NodeConfig is the Schema for the workerconfigs API.
type NodeConfig struct {
metav1.TypeMeta `json:",inline"`
metav1.ObjectMeta `json:"metadata,omitempty"`

//+optional
// +optional
Spec NodeConfigSpec `json:"spec,omitempty"`
}

Expand Down Expand Up @@ -63,6 +65,14 @@ func (s NodeConfigSpec) VariableSchema() clusterv1.VariableSchema {
return nodeConfigProps
}

func (s *NodeConfigSpec) ToClusterVariable(name string) (*clusterv1.ClusterVariable, error) {
return variables.MarshalToClusterVariable(name, s)
}

func (s *NodeConfigSpec) FromClusterVariable(clusterVariable *clusterv1.ClusterVariable) error {
return variables.UnmarshalClusterVariable(clusterVariable, s)
}

type GenericNodeConfig struct{}

func (GenericNodeConfig) VariableSchema() clusterv1.VariableSchema {
Expand Down
59 changes: 59 additions & 0 deletions api/variables/variables.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
// Copyright 2023 D2iQ, Inc. All rights reserved.
// SPDX-License-Identifier: Apache-2.0

package variables

import (
"encoding/json"
"fmt"

v1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
clusterv1 "sigs.k8s.io/cluster-api/api/v1beta1"
)

func MarshalToClusterVariable[T any](name string, obj T) (*clusterv1.ClusterVariable, error) {
marshaled, err := json.Marshal(obj)
if err != nil {
return nil, fmt.Errorf("failed to marshal variable value %q: %w", name, err)
}
return &clusterv1.ClusterVariable{
Name: name,
Value: v1.JSON{Raw: marshaled},
}, nil
}

func UnmarshalClusterVariable[T any](clusterVariable *clusterv1.ClusterVariable, obj *T) error {
err := json.Unmarshal(clusterVariable.Value.Raw, obj)
if err != nil {
return fmt.Errorf("error unmarshalling variable: %w", err)
}

return nil
}

func GetClusterVariableByName(
name string,
clusterVariables []clusterv1.ClusterVariable,
) (*clusterv1.ClusterVariable, int) {
for i, clusterVar := range clusterVariables {
if clusterVar.Name == name {
return &clusterVar, i
}
}
return nil, -1
}

func GetMachineDeploymentVariableByName(
name string,
machineDeploymentVariables *clusterv1.MachineDeploymentVariables,
) (*clusterv1.ClusterVariable, int) {
if machineDeploymentVariables == nil {
return nil, -1
}
for i, mdVar := range machineDeploymentVariables.Overrides {
if mdVar.Name == name {
return &mdVar, i
}
}
return nil, -1
}
3 changes: 3 additions & 0 deletions charts/cluster-api-runtime-extensions-nutanix/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -77,3 +77,6 @@ A Helm chart for cluster-api-runtime-extensions-nutanix
| service.port | int | `443` | |
| service.type | string | `"ClusterIP"` | |
| tolerations | list | `[{"effect":"NoSchedule","key":"node-role.kubernetes.io/master","operator":"Equal"},{"effect":"NoSchedule","key":"node-role.kubernetes.io/control-plane","operator":"Equal"}]` | Kubernetes pod tolerations |
| webhooks.service.annotations | object | `{}` | |
| webhooks.service.port | int | `443` | |
| webhooks.service.type | string | `"ClusterIP"` | |
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,17 @@
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
name: {{ template "chart.name" . }}-runtimehooks-tls
name: {{ template "chart.name" . }}-service-cert
namespace: {{ .Release.Namespace }}
labels:
{{- include "chart.labels" . | nindent 4 }}
spec:
dnsNames:
- {{ template "chart.name" . }}-runtimehooks.{{ .Release.Namespace }}.svc
- {{ template "chart.name" . }}-runtimehooks.{{ .Release.Namespace }}.svc.cluster.local
- {{ template "chart.name" . }}-webhook-service.{{ .Release.Namespace }}.svc
- {{ template "chart.name" . }}-webhook-service.{{ .Release.Namespace }}.svc.cluster.local
issuerRef:
kind: {{ .Values.certificates.issuer.kind }}
name: {{ template "chart.issuerName" . }}
secretName: {{ template "chart.name" . }}-runtimehooks-tls
secretName: {{ template "chart.name" . }}-service-cert
Original file line number Diff line number Diff line change
Expand Up @@ -28,11 +28,14 @@ spec:
image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default $.Chart.AppVersion }}"
imagePullPolicy: "{{ .Values.image.pullPolicy }}"
args:
- --webhook-cert-dir=/runtimehooks-certs/
- --runtime-webhook-port=9444
- --runtime-webhook-cert-dir=/tmp/k8s-webhook-server/serving-certs/
- --defaults-namespace=$(POD_NAMESPACE)
- --helm-addons-configmap={{ .Values.helmAddonsConfigMap }}
- --cni.cilium.helm-addon.default-values-template-configmap-name={{ .Values.hooks.cni.cilium.helmAddonStrategy.defaultValueTemplateConfigMap.name }}
- --nfd.helm-addon.default-values-template-configmap-name={{ .Values.hooks.nfd.helmAddonStrategy.defaultValueTemplateConfigMap.name }}
- --webhook-port=9443
- --webhook-cert-dir=/tmp/k8s-webhook-server/serving-certs/
{{- range $key, $value := .Values.extraArgs }}
- --{{ $key }}={{ $value }}
{{- end }}
Expand All @@ -43,9 +46,12 @@ spec:
{{- end }}
{{- end }}
ports:
- containerPort: 9443
- containerPort: 9444
name: runtimehooks
protocol: TCP
- containerPort: 9443
name: webhook-server
protocol: TCP
- containerPort: 8080
name: metrics
protocol: TCP
Expand All @@ -62,8 +68,8 @@ spec:
{{- toYaml . | nindent 10 }}
{{- end }}
volumeMounts:
- mountPath: /runtimehooks-certs
name: runtimehooks-cert
- mountPath: /tmp/k8s-webhook-server/serving-certs
name: cert
readOnly: true
livenessProbe:
httpGet:
Expand All @@ -81,7 +87,7 @@ spec:
{{- toYaml . | nindent 8}}
{{- end }}
volumes:
- name: runtimehooks-cert
- name: cert
secret:
defaultMode: 420
secretName: {{ template "chart.name" . }}-runtimehooks-tls
secretName: {{ template "chart.name" . }}-service-cert
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ apiVersion: runtime.cluster.x-k8s.io/v1alpha1
kind: ExtensionConfig
metadata:
annotations:
runtime.cluster.x-k8s.io/inject-ca-from-secret: {{ .Release.Namespace }}/{{ template "chart.name" . }}-runtimehooks-tls
runtime.cluster.x-k8s.io/inject-ca-from-secret: {{ .Release.Namespace }}/{{ template "chart.name" . }}-service-cert
name: {{ template "chart.name" . }}
namespace: {{ .Release.Namespace }}
spec:
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# Copyright 2023 D2iQ, Inc. All rights reserved.
# SPDX-License-Identifier: Apache-2.0

apiVersion: v1
kind: Service
metadata:
annotations:
{{- with .Values.webhooks.service.annotations }}
{{ toYaml . | nindent 4 }}
{{- end }}
labels:
{{- include "chart.labels" . | nindent 4 }}
name: {{ template "chart.name" . }}-webhook-service
namespace: {{ .Release.Namespace }}
spec:
type: {{.Values.webhooks.service.type}}
ports:
- name: https
port: {{ .Values.webhooks.service.port }}
protocol: TCP
targetPort: webhook-server
{{- if and .Values.webhooks.service.nodePort (eq "NodePort" .Values.service.type) }}
nodePort: {{ .Values.webhooks.service.nodePort }}
{{- end }}
selector:
{{- include "chart.selectorLabels" . | nindent 4 }}
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
# Copyright 2023 D2iQ, Inc. All rights reserved.
# SPDX-License-Identifier: Apache-2.0

apiVersion: admissionregistration.k8s.io/v1
kind: MutatingWebhookConfiguration
metadata:
name: {{ template "chart.name" . }}-webhook-configuration
annotations:
cert-manager.io/inject-ca-from: {{ .Release.Namespace }}/{{ template "chart.name" . }}-service-cert
webhooks:
- admissionReviewVersions:
- v1
- v1beta1
clientConfig:
service:
name: {{ template "chart.name" . }}-webhook-service
namespace: {{ .Release.Namespace }}
path: /mutate-cluster-x-k8s-io-v1beta1-cluster
failurePolicy: Fail
matchPolicy: Equivalent
name: default.cluster.cluster.x-k8s.io
rules:
- apiGroups:
- cluster.x-k8s.io
apiVersions:
- v1beta1
operations:
- CREATE
- UPDATE
resources:
- clusters
sideEffects: None
6 changes: 6 additions & 0 deletions charts/cluster-api-runtime-extensions-nutanix/values.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -128,3 +128,9 @@ tolerations:

# -- Priority class to be used for the pod.
priorityClassName: system-cluster-critical

webhooks:
service:
annotations: {}
type: ClusterIP
port: 443
19 changes: 19 additions & 0 deletions cmd/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import (
"sigs.k8s.io/controller-runtime/pkg/healthz"
"sigs.k8s.io/controller-runtime/pkg/manager"
metricsserver "sigs.k8s.io/controller-runtime/pkg/metrics/server"
"sigs.k8s.io/controller-runtime/pkg/webhook"

caaphv1 "github.com/d2iq-labs/cluster-api-runtime-extensions-nutanix/api/external/sigs.k8s.io/cluster-api-addon-provider-helm/api/v1alpha1"
"github.com/d2iq-labs/cluster-api-runtime-extensions-nutanix/common/pkg/capi/clustertopology/handlers"
Expand All @@ -38,6 +39,7 @@ import (
nutanixmutation "github.com/d2iq-labs/cluster-api-runtime-extensions-nutanix/pkg/handlers/nutanix/mutation"
nutanixworkerconfig "github.com/d2iq-labs/cluster-api-runtime-extensions-nutanix/pkg/handlers/nutanix/workerconfig"
"github.com/d2iq-labs/cluster-api-runtime-extensions-nutanix/pkg/handlers/options"
"github.com/d2iq-labs/cluster-api-runtime-extensions-nutanix/webhooks"
)

func main() {
Expand Down Expand Up @@ -80,6 +82,9 @@ func main() {

runtimeWebhookServerOpts := server.NewServerOptions()

// mutating/validating webhook server options
webhookServerOpts := webhooks.NewOptions()

globalOptions := options.NewGlobalOptions()

genericLifecycleHandlers := lifecycle.New(globalOptions)
Expand All @@ -89,6 +94,7 @@ func main() {
logsv1.AddFlags(logOptions, pflag.CommandLine)
globalOptions.AddFlags(pflag.CommandLine)
runtimeWebhookServerOpts.AddFlags(pflag.CommandLine)
webhookServerOpts.AddFlags(pflag.CommandLine)
genericLifecycleHandlers.AddFlags(pflag.CommandLine)
pflag.CommandLine.SetNormalizeFunc(cliflag.WordSepNormalizeFunc)
pflag.CommandLine.AddGoFlagSet(flag.CommandLine)
Expand All @@ -105,6 +111,14 @@ func main() {
// Add the klog logger in the context.
ctrl.SetLogger(klog.Background())

// Setup mutating/validating webhook server
mgrOptions.WebhookServer = webhook.NewServer(
webhook.Options{
Port: webhookServerOpts.WebhookPort,
CertDir: webhookServerOpts.WebhookCertDir,
},
)

signalCtx := ctrl.SetupSignalHandler()

mgr, err := newManager(mgrOptions)
Expand Down Expand Up @@ -154,6 +168,11 @@ func main() {
os.Exit(1)
}

if err := (&webhooks.Cluster{}).SetupWebhookWithManager(mgr); err != nil {
setupLog.Error(err, "unable to create webhook", "webhook", "Cluster")
os.Exit(1)
}

if err := mgr.Start(signalCtx); err != nil {
setupLog.Error(err, "unable to start controller manager")
os.Exit(1)
Expand Down
6 changes: 3 additions & 3 deletions common/pkg/server/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,13 +48,13 @@ func NewServerOptions() *ServerOptions {
}

func (s *ServerOptions) AddFlags(fs *pflag.FlagSet) {
fs.IntVar(&s.webhookPort, "webhook-port", s.webhookPort, "Webhook Server port")
fs.IntVar(&s.webhookPort, "runtime-webhook-port", s.webhookPort, "Runtime webhook server port")

fs.StringVar(
&s.webhookCertDir,
"webhook-cert-dir",
"runtime-webhook-cert-dir",
s.webhookCertDir,
"Runtime hooks server cert dir.",
"Runtime webhook server cert dir",
)
}

Expand Down
5 changes: 4 additions & 1 deletion make/go.mk
Original file line number Diff line number Diff line change
Expand Up @@ -190,7 +190,10 @@ go-fix.%: ; $(info $(M) go fixing $* module)
go-generate: ## Runs go generate
go-generate: ; $(info $(M) running go generate)
go generate -x ./...
controller-gen paths="./..." rbac:headerFile="hack/license-header.yaml.txt",roleName=cluster-api-runtime-extensions-nutanix-manager-role output:rbac:artifacts:config=charts/cluster-api-runtime-extensions-nutanix/templates
controller-gen \
paths="./..." \
rbac:headerFile="hack/license-header.yaml.txt",roleName=cluster-api-runtime-extensions-nutanix-manager-role \
output:rbac:artifacts:config=charts/cluster-api-runtime-extensions-nutanix/templates
sed --in-place 's/cluster-api-runtime-extensions-nutanix-manager-role/{{ include "chart.name" . }}-manager-role/' charts/cluster-api-runtime-extensions-nutanix/templates/role.yaml
controller-gen paths="./api/v1alpha1/..." object:headerFile="hack/license-header.go.txt" output:object:artifacts:config=/dev/null
$(MAKE) go-fix
Expand Down
Loading

0 comments on commit cba0297

Please sign in to comment.