Skip to content

Commit

Permalink
Merge pull request #16 from qpoint-io/marc-barry/labels
Browse files Browse the repository at this point in the history
Simplify labels to support service, inject or disable.
  • Loading branch information
marc-barry authored Dec 2, 2023
2 parents 264526b + 281928b commit 88a5759
Show file tree
Hide file tree
Showing 3 changed files with 84 additions and 65 deletions.
104 changes: 52 additions & 52 deletions api/v1/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,20 +9,22 @@ import (
"sigs.k8s.io/yaml"
)

const GATEWAY_ANNOTATIONS_CONFIGMAP = "qtap-operator-gateway-pod-annotations-configmap"
const INJECTION_ANNOTATIONS_CONFIGMAP = "qtap-operator-injection-pod-annotations-configmap"
const SERVICE_ANNOTATIONS_CONFIGMAP = "qtap-operator-service-pod-annotations-configmap"
const INJECT_ANNOTATIONS_CONFIGMAP = "qtap-operator-inject-pod-annotations-configmap"
const NAMESPACE_EGRESS_LABEL = "qpoint-egress"
const NAMESPACE_INJECTION_LABEL = "qpoint-injection"
const POD_EGRESS_ANNOTATION = "qpoint.io/egress"
const POD_INJECTION_LABEL = "sidecar.qpoint.io/inject"
const ENABLED = "enabled"
const DISABLED = "disabled"
const TRUE = "true"
const FALSE = "false"
const POD_EGRESS_LABEL = "qpoint.io/egress"

type EgressType string

const (
EgressType_UNDEFINED EgressType = "undefined"
EgressType_DISABLE EgressType = "disable"
EgressType_SERVICE EgressType = "service"
EgressType_INJECT EgressType = "inject"
)

type Config struct {
EnabledEgress bool // Egress routing is enabled
EnabledInjection bool // Sidecar injection is enabled
EgressType EgressType
InjectCa bool
Namespace string
OperatorNamespace string
Expand All @@ -33,8 +35,8 @@ type Config struct {
}

// Config scenarios:
// a) Egress routing is enabled and gateway is disabled via the namespace label or pod annotation. This means that the egress traffic is being routed to the qtap service running somewhere else in the cluster.
// b) Egress routing is enabled and gateway is enabled via the namespace label or pod annotation. This means that the egress traffic is being routed through the qtap sidecar proxy.
// a) Egress routing is enabled and gateway is disabled via the namespace label or pod label. This means that the egress traffic is being routed to the qtap service running somewhere else in the cluster.
// b) Egress routing is enabled and gateway is enabled via the namespace label or pod label. This means that the egress traffic is being routed through the qtap sidecar proxy.
//
// Egress routing is always controlled by the qtap-init container which manipulates iptables rules for routing egress traffic to one of the above qtap setups.

Expand All @@ -45,50 +47,48 @@ func (c *Config) Init(pod *corev1.Pod) error {
return fmt.Errorf("fetching namespace '%s' from the api: %w", c.Namespace, err)
}

// if the namespace is labeled for egress, then we enable. A pod annotation override will be checked below
if namespace.Labels[NAMESPACE_EGRESS_LABEL] == ENABLED {
c.EnabledEgress = true
} else if namespace.Labels[NAMESPACE_EGRESS_LABEL] == DISABLED {
c.EnabledEgress = false
namespaceEgressType := EgressType_UNDEFINED
configMapName := ""

switch v := namespace.Labels[NAMESPACE_EGRESS_LABEL]; EgressType(v) {
case EgressType_DISABLE:
c.EgressType = EgressType_DISABLE
return nil
case EgressType_SERVICE:
c.EgressType = EgressType_SERVICE
namespaceEgressType = EgressType_SERVICE
configMapName = SERVICE_ANNOTATIONS_CONFIGMAP
case EgressType_INJECT:
c.EgressType = EgressType_INJECT
namespaceEgressType = EgressType_INJECT
configMapName = INJECT_ANNOTATIONS_CONFIGMAP
}

// check to see if an annotation is set on the pod to enable or disable egress while also verifying
// if it was enabled for the namespace but needs to be disabled for the pod. If the annotation doesn't exist nothing else needs to be checked
if egress, exists := pod.Annotations[POD_EGRESS_ANNOTATION]; exists {
if c.EnabledEgress && egress == DISABLED {
c.EnabledEgress = false
}

if !c.EnabledEgress && egress == ENABLED {
c.EnabledEgress = true
}
podEgressType := EgressType_UNDEFINED

// order matters as pods override namespaces

switch v := pod.Labels[POD_EGRESS_LABEL]; EgressType(v) {
case EgressType_DISABLE:
c.EgressType = EgressType_DISABLE
return nil
case EgressType_SERVICE:
c.EgressType = EgressType_SERVICE
podEgressType = EgressType_SERVICE
configMapName = SERVICE_ANNOTATIONS_CONFIGMAP
case EgressType_INJECT:
c.EgressType = EgressType_INJECT
podEgressType = EgressType_INJECT
configMapName = INJECT_ANNOTATIONS_CONFIGMAP
}

// if we're enabled
if c.EnabledEgress {
configMapName := GATEWAY_ANNOTATIONS_CONFIGMAP

// if the namespace is labeled for injection, then we enable. A pod annotation override will be checked below
if namespace.Labels[NAMESPACE_INJECTION_LABEL] == ENABLED {
c.EnabledInjection = true
configMapName = INJECTION_ANNOTATIONS_CONFIGMAP
} else if namespace.Labels[NAMESPACE_INJECTION_LABEL] == DISABLED {
c.EnabledInjection = false
}

// check to see if an label is set on the pod to enable or disable injection while also verifying
// if it was enabled for the namespace but needs to be disabled for the pod. If the label doesn't exist nothing else needs to be checked
if inject, exists := pod.Labels[POD_INJECTION_LABEL]; exists {
if c.EnabledInjection && inject == FALSE {
c.EnabledInjection = false
}

if !c.EnabledInjection && inject == TRUE {
c.EnabledInjection = true
configMapName = INJECTION_ANNOTATIONS_CONFIGMAP
}
}
// egress is undefined for the entire namespace (regardless of what the pod label says) or pod and thus return immediately
if namespaceEgressType == EgressType_UNDEFINED && podEgressType == EgressType_UNDEFINED {
c.EgressType = EgressType_UNDEFINED
return nil
}

if configMapName != "" {
// let's fetch the default settings in the configmap
configMap := &corev1.ConfigMap{}
if err := c.Client.Get(c.Ctx, client.ObjectKey{Name: configMapName, Namespace: c.OperatorNamespace}, configMap); err != nil {
Expand Down
41 changes: 30 additions & 11 deletions api/v1/webhook.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,10 +35,9 @@ func (w *Webhook) Handle(ctx context.Context, req admission.Request) admission.R

// initialize a config with defaults
config := &Config{
EgressType: EgressType_UNDEFINED,
Namespace: req.Namespace,
OperatorNamespace: w.Namespace,
EnabledEgress: false,
EnabledInjection: false,
InjectCa: false,
Client: w.ApiClient,
Ctx: ctx,
Expand All @@ -50,8 +49,11 @@ func (w *Webhook) Handle(ctx context.Context, req admission.Request) admission.R
return admission.Errored(http.StatusInternalServerError, err)
}

if config.EnabledEgress {
webhookLog.Info("Qpoint egress enabled, mutating...")
switch v := config.EgressType; EgressType(v) {
case EgressType_SERVICE:
// for this case the pod is mutated for service egress

webhookLog.Info("Qpoint egress to service enabled, mutating...")

// mutate the pod to include egress through the gateway
if err := MutateEgress(pod, config); err != nil {
Expand All @@ -70,21 +72,38 @@ func (w *Webhook) Handle(ctx context.Context, req admission.Request) admission.R
return admission.Errored(http.StatusInternalServerError, err)
}
}
case EgressType_INJECT:
// for this case the pod is mutated for sidecar egress

} else {
webhookLog.Info("Qpoint egress not enabled, ignoring...")
}
webhookLog.Info("Qpoint egress to sidecar enabled, mutating...")

if config.EnabledInjection {
webhookLog.Info("Qpoint injection enabled, mutating...")
// mutate the pod to include egress through the gateway
if err := MutateEgress(pod, config); err != nil {
webhookLog.Error(err, "failed to mutate pod for egress")
return admission.Errored(http.StatusInternalServerError, err)
}

// mutate the pod to include the sidecar
if err := MutateInjection(pod, config); err != nil {
webhookLog.Error(err, "failed to mutate pod for injection")
return admission.Errored(http.StatusInternalServerError, err)
}
} else {
webhookLog.Info("Qpoint injection not enabled, ignoring...")

if config.InjectCa {
if err := EnsureAssetsInNamespace(config); err != nil {
webhookLog.Error(err, "failed to add assets to namespace for ca injection")
return admission.Errored(http.StatusInternalServerError, err)
}

if err := MutateCaInjection(pod, config); err != nil {
webhookLog.Error(err, "failed to mutate pod for ca injection")
return admission.Errored(http.StatusInternalServerError, err)
}
}
case EgressType_DISABLE:
webhookLog.Info("Qpoint egress disabled, ignoring...")
default:
webhookLog.Info("Qpoint egress not enabled, ignoring...")
}

marshaledPod, err := json.Marshal(pod)
Expand Down
4 changes: 2 additions & 2 deletions config/webhook/configmap.yaml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
apiVersion: v1
kind: ConfigMap
metadata:
name: gateway-pod-annotations-configmap
name: service-pod-annotations-configmap
namespace: system
data:
annotations.yaml: |
Expand All @@ -13,7 +13,7 @@ data:
apiVersion: v1
kind: ConfigMap
metadata:
name: injection-pod-annotations-configmap
name: inject-pod-annotations-configmap
namespace: system
data:
annotations.yaml: |
Expand Down

0 comments on commit 88a5759

Please sign in to comment.