linkerd2/pkg/inject/uninject.go

101 lines
2.9 KiB
Go

package inject
import (
"strings"
"github.com/linkerd/linkerd2/pkg/k8s"
v1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)
// Uninject removes from the workload in conf the init and proxy containers,
// the TLS volumes and the extra annotations/labels that were added
func (conf *ResourceConfig) Uninject(report *Report) ([]byte, error) {
if conf.IsNamespace() || conf.IsService() {
uninjectObjectMeta(conf.workload.Meta, report)
return conf.YamlMarshalObj()
}
if conf.pod.spec == nil {
return nil, nil
}
conf.uninjectPodSpec(report)
if conf.workload.Meta != nil {
uninjectObjectMeta(conf.workload.Meta, report)
}
uninjectObjectMeta(conf.pod.meta, report)
return conf.YamlMarshalObj()
}
// Given a PodSpec, update the PodSpec in place with the sidecar
// and init-container uninjected
func (conf *ResourceConfig) uninjectPodSpec(report *Report) {
t := conf.pod.spec
initContainers := []v1.Container{}
for _, container := range t.InitContainers {
switch container.Name {
case k8s.InitContainerName:
report.Uninjected.ProxyInit = true
case k8s.ProxyContainerName:
report.Uninjected.Proxy = true
default:
initContainers = append(initContainers, container)
}
}
t.InitContainers = initContainers
containers := []v1.Container{}
for _, container := range t.Containers {
if container.Name != k8s.ProxyContainerName {
containers = append(containers, container)
} else {
report.Uninjected.Proxy = true
}
}
t.Containers = containers
volumes := []v1.Volume{}
for _, volume := range t.Volumes {
if volume.Name != k8s.IdentityEndEntityVolumeName && volume.Name != k8s.InitXtablesLockVolumeMountName && volume.Name != k8s.LinkerdTokenVolumeMountName {
volumes = append(volumes, volume)
}
}
t.Volumes = volumes
}
func uninjectObjectMeta(t *metav1.ObjectMeta, report *Report) {
// We only uninject control plane components in the context
// of doing an inject --manual. This is done as a way to update
// something about the injection configuration - for example
// adding a debug sidecar to the identity service.
// With that in mind it is not really necessary to strip off
// the linkerd.io/* metadata from the pod during uninjection.
// This is why we skip that part for control plane components.
// Furthermore the latter will never have linkerd.io/inject as
// they are always manually injected.
if _, ok := t.Labels[k8s.ControllerComponentLabel]; !ok {
newAnnotations := make(map[string]string)
for key, val := range t.Annotations {
if !strings.HasPrefix(key, k8s.Prefix) ||
(key == k8s.ProxyInjectAnnotation && val == k8s.ProxyInjectDisabled) {
newAnnotations[key] = val
} else {
report.Uninjected.Proxy = true
}
}
t.Annotations = newAnnotations
labels := make(map[string]string)
for key, val := range t.Labels {
if !strings.HasPrefix(key, k8s.Prefix) {
labels[key] = val
}
}
t.Labels = labels
}
}