Created
February 5, 2022 12:50
-
-
Save fl64/0d6ec08e9066a55cbc735a1d302560ef to your computer and use it in GitHub Desktop.
kubebuilder mutating webhook
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| /* | |
| Copyright 2022 fl64 <[email protected]>. | |
| */ | |
| package main | |
| import ( | |
| "flag" | |
| "github.com/fl64/gitlab-job-mutator/mutator" | |
| "os" | |
| "sigs.k8s.io/controller-runtime/pkg/webhook" | |
| // Import all Kubernetes client auth plugins (e.g. Azure, GCP, OIDC, etc.) | |
| // to ensure that exec-entrypoint and run can make use of them. | |
| _ "k8s.io/client-go/plugin/pkg/client/auth" | |
| "k8s.io/apimachinery/pkg/runtime" | |
| utilruntime "k8s.io/apimachinery/pkg/util/runtime" | |
| clientgoscheme "k8s.io/client-go/kubernetes/scheme" | |
| ctrl "sigs.k8s.io/controller-runtime" | |
| "sigs.k8s.io/controller-runtime/pkg/healthz" | |
| "sigs.k8s.io/controller-runtime/pkg/log/zap" | |
| //+kubebuilder:scaffold:imports | |
| ) | |
| var ( | |
| scheme = runtime.NewScheme() | |
| setupLog = ctrl.Log.WithName("setup") | |
| ) | |
| func init() { | |
| utilruntime.Must(clientgoscheme.AddToScheme(scheme)) | |
| //+kubebuilder:scaffold:scheme | |
| } | |
| func main() { | |
| var metricsAddr string | |
| var enableLeaderElection bool | |
| var probeAddr string | |
| flag.StringVar(&metricsAddr, "metrics-bind-address", ":8080", "The address the metric endpoint binds to.") | |
| flag.StringVar(&probeAddr, "health-probe-bind-address", ":8081", "The address the probe endpoint binds to.") | |
| flag.BoolVar(&enableLeaderElection, "leader-elect", false, | |
| "Enable leader election for controller manager. "+ | |
| "Enabling this will ensure there is only one active controller manager.") | |
| opts := zap.Options{ | |
| Development: true, | |
| } | |
| opts.BindFlags(flag.CommandLine) | |
| flag.Parse() | |
| ctrl.SetLogger(zap.New(zap.UseFlagOptions(&opts))) | |
| mgr, err := ctrl.NewManager(ctrl.GetConfigOrDie(), ctrl.Options{ | |
| Scheme: scheme, | |
| MetricsBindAddress: metricsAddr, | |
| Port: 9443, | |
| HealthProbeBindAddress: probeAddr, | |
| LeaderElection: enableLeaderElection, | |
| LeaderElectionID: "e3ba4979.fl64.net", | |
| }) | |
| if err != nil { | |
| setupLog.Error(err, "unable to start manager") | |
| os.Exit(1) | |
| } | |
| mutator := &mutator.PodMutator{ | |
| Client: mgr.GetClient(), | |
| } | |
| setupLog.Info("Register webhook") | |
| mgr.GetWebhookServer().Register("/mutate-core-v1-pod", &webhook.Admission{Handler: mutator}) | |
| setupLog.Info("Register finished") | |
| //+kubebuilder:scaffold:builder | |
| if err := mgr.AddHealthzCheck("healthz", healthz.Ping); err != nil { | |
| setupLog.Error(err, "unable to set up health check") | |
| os.Exit(1) | |
| } | |
| if err := mgr.AddReadyzCheck("readyz", healthz.Ping); err != nil { | |
| setupLog.Error(err, "unable to set up ready check") | |
| os.Exit(1) | |
| } | |
| setupLog.Info("starting manager") | |
| if err := mgr.Start(ctrl.SetupSignalHandler()); err != nil { | |
| setupLog.Error(err, "problem running manager") | |
| os.Exit(1) | |
| } | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| /* | |
| Copyright 2022 fl64 <[email protected]>. | |
| */ | |
| package mutator | |
| import ( | |
| "context" | |
| "encoding/json" | |
| corev1 "k8s.io/api/core/v1" | |
| "net/http" | |
| "sigs.k8s.io/controller-runtime/pkg/client" | |
| logf "sigs.k8s.io/controller-runtime/pkg/log" | |
| "sigs.k8s.io/controller-runtime/pkg/webhook/admission" | |
| ) | |
| // log is for logging in this package. | |
| var podlog = logf.Log.WithName("pod-resource") | |
| // TODO(user): EDIT THIS FILE! THIS IS SCAFFOLDING FOR YOU TO OWN! | |
| //+kubebuilder:webhook:path=/mutate-core-v1-pod,mutating=true,failurePolicy=fail,sideEffects=None,groups=core,resources=pods,verbs=create;update,versions=v1,name=mpod.kb.io,admissionReviewVersions=v1 | |
| type PodMutator struct { | |
| Client client.Client | |
| decoder *admission.Decoder | |
| } | |
| func (p *PodMutator) Handle(ctx context.Context, req admission.Request) admission.Response { | |
| podlog.Info("Start mutator") | |
| pod := &corev1.Pod{} | |
| err := p.decoder.Decode(req, pod) | |
| if err != nil { | |
| return admission.Errored(http.StatusBadRequest, err) | |
| } | |
| sidecar := corev1.Container{ | |
| Name: "nginx", | |
| Image: "nginx:1.16", | |
| ImagePullPolicy: corev1.PullIfNotPresent, | |
| Ports: []corev1.ContainerPort{ | |
| { | |
| Name: "http", | |
| ContainerPort: 80, | |
| }, | |
| }, | |
| } | |
| pod.Spec.Containers = append(pod.Spec.Containers, sidecar) | |
| marshaledPod, err := json.Marshal(pod) | |
| if err != nil { | |
| return admission.Errored(http.StatusInternalServerError, err) | |
| } | |
| return admission.PatchResponseFromRaw(req.Object.Raw, marshaledPod) | |
| } | |
| func (p *PodMutator) InjectDecoder(d *admission.Decoder) error { | |
| p.decoder = d | |
| return nil | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment