From 8e7a7d21c2724b9c0dc22eca3ea8370795c6c06a Mon Sep 17 00:00:00 2001 From: Ivan Sim Date: Mon, 25 Mar 2019 15:38:26 -0700 Subject: [PATCH] Append the config annotations to the pod's meta before creating the patch This ensures that any configs provided via the CLI options are persisted as annotations before the configs override. Signed-off-by: Ivan Sim --- cli/cmd/inject.go | 20 +++++++++----- controller/proxy-injector/webhook.go | 5 ++-- pkg/inject/inject.go | 39 +++++++++++++++++++++++----- pkg/inject/patch.go | 4 +-- pkg/inject/patch_test.go | 2 +- 5 files changed, 51 insertions(+), 19 deletions(-) diff --git a/cli/cmd/inject.go b/cli/cmd/inject.go index 1f141af9ab153..7c3922e1701cd 100644 --- a/cli/cmd/inject.go +++ b/cli/cmd/inject.go @@ -131,6 +131,14 @@ func (rt resourceTransformerInject) transform(bytes []byte) ([]byte, []inject.Re r := inject.Report{UnsupportedResource: true} return bytes, []inject.Report{r}, nil } + + conf.AppendPodAnnotations(map[string]string{ + k8s.CreatedByAnnotation: k8s.CreatedByAnnotationValue(), + }) + if len(rt.overrideAnnotations) > 0 { + conf.AppendPodAnnotations(rt.overrideAnnotations) + } + p, reports, err := conf.GetPatch(bytes, inject.ShouldInjectCLI) if err != nil { return nil, nil, err @@ -139,11 +147,6 @@ func (rt resourceTransformerInject) transform(bytes []byte) ([]byte, []inject.Re return bytes, reports, nil } - for annotation, value := range rt.overrideAnnotations { - p.AddPodAnnotation(annotation, value) - } - p.AddPodAnnotation(k8s.CreatedByAnnotation, k8s.CreatedByAnnotationValue()) - patchJSON, err := p.Marshal() if err != nil { return nil, nil, err @@ -286,7 +289,9 @@ func (options *injectOptions) fetchConfigsOrDefault() (*config.All, error) { return api.Config(context.Background(), &public.Empty{}) } -// overrideConfigs uses command-line overrides to update the provided configs +// overrideConfigs uses command-line overrides to update the provided configs. +// the overrideAnnotations map keeps track of which configs are overridden, by +// storing the corresponding annotations and values. func (options *injectOptions) overrideConfigs(configs *config.All, overrideAnnotations map[string]string) { if len(options.ignoreInboundPorts) > 0 { configs.Proxy.IgnoreInboundPorts = toPorts(options.ignoreInboundPorts) @@ -346,6 +351,9 @@ func (options *injectOptions) overrideConfigs(configs *config.All, overrideAnnot overrideAnnotations[k8s.ProxyLogLevelAnnotation] = options.proxyLogLevel } + // keep track of this option because its true/false value results in different + // values being assigned to the LINKERD2_PROXY_DESTINATION_PROFILE_SUFFIXES + // env var. Its annotation is added only if its value is true. configs.Proxy.DisableExternalProfiles = options.disableExternalProfiles if options.disableExternalProfiles { overrideAnnotations[k8s.ProxyDisableExternalProfilesAnnotation] = "true" diff --git a/controller/proxy-injector/webhook.go b/controller/proxy-injector/webhook.go index 289818e691190..ffc7eeed87cdd 100644 --- a/controller/proxy-injector/webhook.go +++ b/controller/proxy-injector/webhook.go @@ -120,6 +120,9 @@ func (w *Webhook) inject(request *admissionv1beta1.AdmissionRequest) (*admission return admissionResponse, nil } + conf.AppendPodAnnotations(map[string]string{ + k8s.CreatedByAnnotation: fmt.Sprintf("linkerd/proxy-injector %s", version.Version), + }) p, _, err := conf.GetPatch(request.Object.Raw, inject.ShouldInjectWebhook) if err != nil { return nil, err @@ -129,8 +132,6 @@ func (w *Webhook) inject(request *admissionv1beta1.AdmissionRequest) (*admission return admissionResponse, nil } - p.AddPodAnnotation(k8s.CreatedByAnnotation, fmt.Sprintf("linkerd/proxy-injector %s", version.Version)) - // When adding workloads through `kubectl apply` the spec template labels are // automatically copied to the workload's main metadata section. // This doesn't happen when adding labels through the webhook. So we manually diff --git a/pkg/inject/inject.go b/pkg/inject/inject.go index 760a273d65c64..bbe86f83cda90 100644 --- a/pkg/inject/inject.go +++ b/pkg/inject/inject.go @@ -90,9 +90,10 @@ type ResourceConfig struct { pod struct { // Meta is the pod's metadata. It's exported so that the YAML marshaling // will work in the ParseMeta() function. - Meta *metav1.ObjectMeta `json:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"` - labels map[string]string - spec *v1.PodSpec + Meta *metav1.ObjectMeta `json:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"` + labels map[string]string + annotations map[string]string + spec *v1.PodSpec } } @@ -105,6 +106,7 @@ func NewResourceConfig(configs *config.All) *ResourceConfig { config.pod.Meta = &metav1.ObjectMeta{} config.pod.labels = map[string]string{k8s.ControllerNSLabel: configs.GetGlobal().GetLinkerdNamespace()} + config.pod.annotations = map[string]string{} return config } @@ -143,6 +145,13 @@ func (conf *ResourceConfig) WithProxyOutboundCapacity(m map[string]uint) *Resour return conf } +// AppendPodAnnotations appends the given annotations to the pod spec in conf +func (conf *ResourceConfig) AppendPodAnnotations(annotations map[string]string) { + for annotation, value := range annotations { + conf.pod.annotations[annotation] = value + } +} + // YamlMarshalObj returns the yaml for the workload in conf func (conf *ResourceConfig) YamlMarshalObj() ([]byte, error) { return yaml.Marshal(conf.workload.obj) @@ -194,8 +203,8 @@ func (conf *ResourceConfig) GetPatch( if conf.pod.spec != nil { report.update(conf) if shouldInject(conf, report) { - conf.injectPodSpec(patch) conf.injectObjectMeta(patch) + conf.injectPodSpec(patch) } } else { report.UnsupportedResource = true @@ -354,6 +363,10 @@ func (conf *ResourceConfig) parse(bytes []byte) error { conf.pod.Meta = &v.ObjectMeta } + if conf.pod.Meta.Annotations == nil { + conf.pod.Meta.Annotations = map[string]string{} + } + return nil } @@ -557,17 +570,29 @@ func (conf *ResourceConfig) injectObjectMeta(patch *Patch) { if len(conf.pod.Meta.Annotations) == 0 { patch.addPodAnnotationsRoot() } - patch.AddPodAnnotation(k8s.ProxyVersionAnnotation, conf.configs.GetGlobal().GetVersion()) + + patch.addPodAnnotation(k8s.ProxyVersionAnnotation, conf.configs.GetGlobal().GetVersion()) if conf.configs.GetGlobal().GetIdentityContext() != nil { - patch.AddPodAnnotation(k8s.IdentityModeAnnotation, k8s.IdentityModeDefault) + patch.addPodAnnotation(k8s.IdentityModeAnnotation, k8s.IdentityModeDefault) } else { - patch.AddPodAnnotation(k8s.IdentityModeAnnotation, k8s.IdentityModeDisabled) + patch.addPodAnnotation(k8s.IdentityModeAnnotation, k8s.IdentityModeDisabled) } for k, v := range conf.pod.labels { patch.addPodLabel(k, v) } + + for k, v := range conf.pod.annotations { + patch.addPodAnnotation(k, v) + } + + // append any additional pod annotations to the pod's meta. + // for e.g., annotations that were converted from CLI inject options. + for annotation, value := range conf.pod.annotations { + conf.pod.Meta.Annotations[annotation] = value + } + } // AddRootLabels adds all the pod labels into the root workload (e.g. Deployment) diff --git a/pkg/inject/patch.go b/pkg/inject/patch.go index 366538275c041..a2e3e64515a63 100644 --- a/pkg/inject/patch.go +++ b/pkg/inject/patch.go @@ -120,9 +120,7 @@ func (p *Patch) addPodAnnotationsRoot() { }) } -// AddPodAnnotation creates an 'add' JSON patch operation structure to append -// the given annotation and value. -func (p *Patch) AddPodAnnotation(key, value string) { +func (p *Patch) addPodAnnotation(key, value string) { p.patchOps = append(p.patchOps, &patchOp{ Op: "add", Path: p.patchPathPodAnnotations + "/" + escapeKey(key), diff --git a/pkg/inject/patch_test.go b/pkg/inject/patch_test.go index 1651ab1d5bd8c..13381bf24c0cf 100644 --- a/pkg/inject/patch_test.go +++ b/pkg/inject/patch_test.go @@ -41,7 +41,7 @@ func TestPatch(t *testing.T) { //actual.addVolumeRoot() //actual.addVolume(secrets) actual.addPodLabel(k8sPkg.ControllerNSLabel, controllerNamespace) - actual.AddPodAnnotation(k8sPkg.CreatedByAnnotation, createdBy) + actual.addPodAnnotation(k8sPkg.CreatedByAnnotation, createdBy) expected := NewPatchDeployment() expected.patchOps = []*patchOp{