4 Commits

Author SHA1 Message Date
Dimitris Karakasilis
2250450b88 Don't mutate original Pod's labels
because we don't want to, plus annotations may not fit in labels
because they have different character limit.

Fix for error about 63 character limit

Signed-off-by: Dimitris Karakasilis <jimmykarily@gmail.com>
2022-12-06 12:41:42 +00:00
Ettore Di Giacinto
b4a78705dd Inject nethost by default in entangled pods 2022-12-05 16:09:07 +01:00
mudler
b25f31d789 Add kubesplit target 2022-11-14 23:58:12 +01:00
mudler
daab27404c Allow to propagate envs 2022-11-14 23:52:21 +01:00
6 changed files with 181 additions and 39 deletions

View File

@@ -275,4 +275,9 @@ unit-tests: test_deps
e2e-tests:
KUBE_VERSION=${KUBE_VERSION} $(ROOT_DIR)/script/test.sh
kind-e2e-tests: kind-setup install undeploy-dev deploy-dev e2e-tests
kind-e2e-tests: kind-setup install undeploy-dev deploy-dev e2e-tests
kubesplit: manifests kustomize
rm -rf helm-chart
mkdir helm-chart
$(KUSTOMIZE) build config/default | kubesplit -helm helm-chart

View File

@@ -29,13 +29,14 @@ type EntanglementSpec struct {
// INSERT ADDITIONAL SPEC FIELDS - desired state of cluster
// Important: Run "make" to regenerate code after modifying this file
ServiceUUID string `json:"serviceUUID,omitempty"`
ServiceRef *string `json:"serviceRef,omitempty"`
SecretRef *string `json:"secretRef,omitempty"`
Host string `json:"host,omitempty"`
Port string `json:"port,omitempty"`
HostNetwork bool `json:"hostNetwork,omitempty"`
Inbound bool `json:"inbound,omitempty"`
ServiceUUID string `json:"serviceUUID,omitempty"`
ServiceRef *string `json:"serviceRef,omitempty"`
SecretRef *string `json:"secretRef,omitempty"`
Host string `json:"host,omitempty"`
Port string `json:"port,omitempty"`
HostNetwork bool `json:"hostNetwork,omitempty"`
Inbound bool `json:"inbound,omitempty"`
Envs []v1.EnvVar `json:"env,omitempty"`
// +kubebuilder:validation:Optional
ServiceSpec *v1.ServiceSpec `json:"serviceSpec,omitEmpty"`
}

View File

@@ -98,6 +98,13 @@ func (in *EntanglementSpec) DeepCopyInto(out *EntanglementSpec) {
*out = new(string)
**out = **in
}
if in.Envs != nil {
in, out := &in.Envs, &out.Envs
*out = make([]v1.EnvVar, len(*in))
for i := range *in {
(*in)[i].DeepCopyInto(&(*out)[i])
}
}
if in.ServiceSpec != nil {
in, out := &in.ServiceSpec, &out.ServiceSpec
*out = new(v1.ServiceSpec)

View File

@@ -35,6 +35,110 @@ spec:
spec:
description: EntanglementSpec defines the desired state of Entanglement
properties:
env:
items:
description: EnvVar represents an environment variable present in
a Container.
properties:
name:
description: Name of the environment variable. Must be a C_IDENTIFIER.
type: string
value:
description: 'Variable references $(VAR_NAME) are expanded using
the previously defined environment variables in the container
and any service environment variables. If a variable cannot
be resolved, the reference in the input string will be unchanged.
Double $$ are reduced to a single $, which allows for escaping
the $(VAR_NAME) syntax: i.e. "$$(VAR_NAME)" will produce the
string literal "$(VAR_NAME)". Escaped references will never
be expanded, regardless of whether the variable exists or
not. Defaults to "".'
type: string
valueFrom:
description: Source for the environment variable's value. Cannot
be used if value is not empty.
properties:
configMapKeyRef:
description: Selects a key of a ConfigMap.
properties:
key:
description: The key to select.
type: string
name:
description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
TODO: Add other useful fields. apiVersion, kind, uid?'
type: string
optional:
description: Specify whether the ConfigMap or its key
must be defined
type: boolean
required:
- key
type: object
fieldRef:
description: 'Selects a field of the pod: supports metadata.name,
metadata.namespace, `metadata.labels[''<KEY>'']`, `metadata.annotations[''<KEY>'']`,
spec.nodeName, spec.serviceAccountName, status.hostIP,
status.podIP, status.podIPs.'
properties:
apiVersion:
description: Version of the schema the FieldPath is
written in terms of, defaults to "v1".
type: string
fieldPath:
description: Path of the field to select in the specified
API version.
type: string
required:
- fieldPath
type: object
resourceFieldRef:
description: 'Selects a resource of the container: only
resources limits and requests (limits.cpu, limits.memory,
limits.ephemeral-storage, requests.cpu, requests.memory
and requests.ephemeral-storage) are currently supported.'
properties:
containerName:
description: 'Container name: required for volumes,
optional for env vars'
type: string
divisor:
anyOf:
- type: integer
- type: string
description: Specifies the output format of the exposed
resources, defaults to "1"
pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$
x-kubernetes-int-or-string: true
resource:
description: 'Required: resource to select'
type: string
required:
- resource
type: object
secretKeyRef:
description: Selects a key of a secret in the pod's namespace
properties:
key:
description: The key of the secret to select from. Must
be a valid secret key.
type: string
name:
description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
TODO: Add other useful fields. apiVersion, kind, uid?'
type: string
optional:
description: Specify whether the Secret or its key must
be defined
type: boolean
required:
- key
type: object
type: object
required:
- name
type: object
type: array
host:
type: string
hostNetwork:

View File

@@ -40,25 +40,26 @@ func (r *EntanglementReconciler) genDeployment(ent entanglev1alpha1.Entanglement
}
}
v := ent.Spec.Envs
v = append(v, v1.EnvVar{
Name: "EDGEVPNTOKEN",
ValueFrom: &v1.EnvVarSource{
SecretKeyRef: &v1.SecretKeySelector{
Key: "network_token",
LocalObjectReference: v1.LocalObjectReference{
Name: *ent.Spec.SecretRef,
},
},
},
})
expose := v1.Container{
ImagePullPolicy: v1.PullAlways,
SecurityContext: &v1.SecurityContext{Privileged: &privileged},
Name: "entanglement",
Image: r.EntangleServiceImage,
Env: []v1.EnvVar{
{
Name: "EDGEVPNTOKEN",
ValueFrom: &v1.EnvVarSource{
SecretKeyRef: &v1.SecretKeySelector{
Key: "network_token",
LocalObjectReference: v1.LocalObjectReference{
Name: *ent.Spec.SecretRef,
},
},
},
},
},
Command: []string{"/usr/bin/edgevpn"},
Env: v,
Command: []string{"/usr/bin/edgevpn"},
}
cmd := "service-add"

View File

@@ -5,6 +5,7 @@ import (
"encoding/json"
"fmt"
"net/http"
"strings"
corev1 "k8s.io/api/core/v1"
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
@@ -34,8 +35,10 @@ var (
EntanglementNameLabel = "entanglement.kairos.io/name"
EntanglementServiceLabel = "entanglement.kairos.io/service"
EntanglementDirectionLabel = "entanglement.kairos.io/direction"
EntanglementNetHost = "entanglement.kairos.io/nethost"
EntanglementPortLabel = "entanglement.kairos.io/target_port"
EntanglementHostLabel = "entanglement.kairos.io/host"
EnvPrefix = "entanglement.kairos.io/env."
)
func (w *Webhook) SetupWebhookWithManager(mgr manager.Manager) error {
@@ -52,17 +55,21 @@ func (w *Webhook) SetupWebhookWithManager(mgr manager.Manager) error {
}
func (w *Webhook) Mutate(ctx context.Context, request admission.Request, object runtime.Object) admission.Response {
_ = log.FromContext(ctx)
pod := object.(*corev1.Pod)
// Let user use both label and annotations
info := pod.Labels
info := make(map[string]string)
// Annotations take precedence
for ann, v := range pod.Annotations {
info[ann] = v
for k, v := range pod.Labels {
info[k] = v
}
// Annotations take precedence
for k, v := range pod.Annotations {
info[k] = v
}
entanglementName, exists := info[EntanglementNameLabel]
@@ -70,6 +77,26 @@ func (w *Webhook) Mutate(ctx context.Context, request admission.Request, object
return admission.Allowed("")
}
envs := []corev1.EnvVar{
{
Name: "EDGEVPNTOKEN",
ValueFrom: &corev1.EnvVarSource{
SecretKeyRef: &corev1.SecretKeySelector{
Key: "network_token",
LocalObjectReference: corev1.LocalObjectReference{
Name: entanglementName,
},
},
},
}}
for k, v := range info {
if strings.HasPrefix(k, EnvPrefix) {
env := strings.ReplaceAll(k, EnvPrefix, "")
envs = append(envs, corev1.EnvVar{Name: env, Value: v})
}
}
entanglementPort, exists := info[EntanglementPortLabel]
if !exists {
return admission.Allowed("")
@@ -93,6 +120,15 @@ func (w *Webhook) Mutate(ctx context.Context, request admission.Request, object
}
podCopy := pod.DeepCopy()
hostNetwork, exists := info[EntanglementNetHost]
// By default it injects hostnetwork, however if set to false it does enforces it to false
if exists && hostNetwork == "false" {
podCopy.Spec.HostNetwork = false
} else {
podCopy.Spec.HostNetwork = true
}
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())
@@ -110,19 +146,7 @@ func (w *Webhook) Mutate(ctx context.Context, request admission.Request, object
ImagePullPolicy: corev1.PullAlways,
Command: []string{"/usr/bin/edgevpn"},
Args: []string{cmd, entanglementService, fmt.Sprintf("%s:%s", host, entanglementPort), "--log-level", w.LogLevel},
Env: []corev1.EnvVar{
{
Name: "EDGEVPNTOKEN",
ValueFrom: &corev1.EnvVarSource{
SecretKeyRef: &corev1.SecretKeySelector{
Key: "network_token",
LocalObjectReference: corev1.LocalObjectReference{
Name: entanglementName,
},
},
},
},
},
Env: envs,
SecurityContext: &corev1.SecurityContext{Privileged: &privileged},
Name: "entanglement",
Image: w.SidecarImage,