mirror of
https://github.com/kairos-io/entangle.git
synced 2025-09-01 00:46:56 +00:00
Initial import
This commit is contained in:
132
controllers/webhooks/pod.go
Normal file
132
controllers/webhooks/pod.go
Normal file
@@ -0,0 +1,132 @@
|
||||
package webhooks
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/http"
|
||||
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/client-go/kubernetes"
|
||||
"sigs.k8s.io/controller-runtime/pkg/client"
|
||||
"sigs.k8s.io/controller-runtime/pkg/log"
|
||||
"sigs.k8s.io/controller-runtime/pkg/manager"
|
||||
"sigs.k8s.io/controller-runtime/pkg/webhook/admission"
|
||||
|
||||
"github.com/snorwin/k8s-generic-webhook/pkg/webhook"
|
||||
)
|
||||
|
||||
type Webhook struct {
|
||||
webhook.MutatingWebhook
|
||||
client.Client
|
||||
clientSet *kubernetes.Clientset
|
||||
Scheme *runtime.Scheme
|
||||
|
||||
SidecarImage string
|
||||
}
|
||||
|
||||
//+kubebuilder:rbac:groups="",resources=secrets,verbs=get;list;watch
|
||||
//+kubebuilder:webhook:verbs=create;update,path=/mutate-entangle-c3os-x-io-v1alpha1-entanglement,mutating=true,failurePolicy=ignore,sideEffects=None,groups=core,resources=pods,versions=v1,name=mentanglement.kb.io,admissionReviewVersions={v1,v1alpha1}
|
||||
|
||||
var (
|
||||
EntanglementNameLabel = "entanglement.c3os-x.io/name"
|
||||
EntanglementServiceLabel = "entanglement.c3os-x.io/service"
|
||||
EntanglementDirectionLabel = "entanglement.c3os-x.io/direction"
|
||||
EntanglementPortLabel = "entanglement.c3os-x.io/target_port"
|
||||
EntanglementHostLabel = "entanglement.c3os-x.io/host"
|
||||
)
|
||||
|
||||
func (w *Webhook) SetupWebhookWithManager(mgr manager.Manager) error {
|
||||
clientset, err := kubernetes.NewForConfig(mgr.GetConfig())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
w.clientSet = clientset
|
||||
|
||||
return webhook.NewGenericWebhookManagedBy(mgr).
|
||||
For(&corev1.Pod{}).
|
||||
WithMutatePath("/mutate-entangle-c3os-x-io-v1alpha1-entanglement").
|
||||
Complete(w)
|
||||
}
|
||||
|
||||
func (w *Webhook) Mutate(ctx context.Context, request admission.Request, object runtime.Object) admission.Response {
|
||||
_ = log.FromContext(ctx)
|
||||
|
||||
pod := object.(*corev1.Pod)
|
||||
entanglementName, exists := pod.Labels[EntanglementNameLabel]
|
||||
if !exists {
|
||||
return admission.Allowed("")
|
||||
}
|
||||
|
||||
entanglementPort, exists := pod.Labels[EntanglementPortLabel]
|
||||
if !exists {
|
||||
return admission.Allowed("")
|
||||
}
|
||||
|
||||
cmd := "service-connect"
|
||||
entanglementDirection, exists := pod.Labels[EntanglementDirectionLabel]
|
||||
if exists && entanglementDirection == "entangle" {
|
||||
cmd = "service-add"
|
||||
}
|
||||
|
||||
host := "127.0.0.1"
|
||||
entanglementHost, exists := pod.Labels[EntanglementHostLabel]
|
||||
if exists && entanglementHost != "" {
|
||||
host = entanglementHost
|
||||
}
|
||||
|
||||
entanglementService, exists := pod.Labels[EntanglementServiceLabel]
|
||||
if !exists {
|
||||
return admission.Allowed("")
|
||||
}
|
||||
|
||||
podCopy := pod.DeepCopy()
|
||||
secret, err := w.clientSet.CoreV1().Secrets(request.Namespace).Get(context.Background(), entanglementName, v1.GetOptions{})
|
||||
if err != nil || secret == nil {
|
||||
return admission.Denied("entanglement secret not found: " + entanglementName + err.Error())
|
||||
}
|
||||
|
||||
privileged := false
|
||||
|
||||
for _, p := range podCopy.Spec.Containers {
|
||||
if p.Name == "entanglement" {
|
||||
return admission.Allowed("already entangled")
|
||||
}
|
||||
}
|
||||
|
||||
servingContainer := corev1.Container{
|
||||
ImagePullPolicy: corev1.PullAlways,
|
||||
Command: []string{"/usr/bin/edgevpn"},
|
||||
Args: []string{cmd, entanglementService, fmt.Sprintf("%s:%s", host, entanglementPort)},
|
||||
Env: []corev1.EnvVar{
|
||||
{
|
||||
Name: "EDGEVPNTOKEN",
|
||||
ValueFrom: &corev1.EnvVarSource{
|
||||
SecretKeyRef: &corev1.SecretKeySelector{
|
||||
Key: "network_token",
|
||||
LocalObjectReference: corev1.LocalObjectReference{
|
||||
Name: entanglementName,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
SecurityContext: &corev1.SecurityContext{Privileged: &privileged},
|
||||
Name: "entanglement",
|
||||
Image: w.SidecarImage,
|
||||
}
|
||||
podCopy.Spec.Containers = append(podCopy.Spec.Containers, servingContainer)
|
||||
|
||||
return patchFromPod(request, podCopy)
|
||||
}
|
||||
|
||||
func patchFromPod(req admission.Request, pod *corev1.Pod) admission.Response {
|
||||
marshaledPod, err := json.Marshal(pod)
|
||||
if err != nil {
|
||||
return admission.Errored(http.StatusInternalServerError, err)
|
||||
}
|
||||
|
||||
return admission.PatchResponseFromRaw(req.Object.Raw, marshaledPod)
|
||||
}
|
Reference in New Issue
Block a user