inject: Refactor report-checking from inject logic (#2379)

The inject logic combines the modification of a pod spec and the
creation of a "report" detailing problems with the pod spec.

This change extracts the report-creation-and-checking logic from the
injection logic to make the contracts of each of these functions
clearer.

No functional changes are intended.
This commit is contained in:
Oliver Gould 2019-02-25 14:18:22 -08:00 committed by GitHub
parent bc735ebdc2
commit 9e67bcb1bc
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 44 additions and 52 deletions

View File

@ -8,7 +8,6 @@ import (
"strconv"
"strings"
"github.com/linkerd/linkerd2/pkg/healthcheck"
"github.com/linkerd/linkerd2/pkg/k8s"
"github.com/spf13/cobra"
v1 "k8s.io/api/core/v1"
@ -115,15 +114,8 @@ func uninjectAndInject(inputs []io.Reader, errWriter, outWriter io.Writer, optio
return runInjectCmd([]io.Reader{&out}, errWriter, outWriter, options)
}
/* Given a ObjectMeta, update ObjectMeta in place with the new labels and
* annotations.
*/
func injectObjectMeta(t *metaV1.ObjectMeta, k8sLabels map[string]string, options *injectOptions, report *injectReport) bool {
report.injectDisabled = injectDisabled(t)
if report.injectDisabled {
return false
}
// injectObjectMeta adds linkerd labels & annotations to the provided ObjectMeta.
func injectObjectMeta(t *metaV1.ObjectMeta, k8sLabels map[string]string, options *injectOptions) {
if t.Annotations == nil {
t.Annotations = make(map[string]string)
}
@ -137,27 +129,10 @@ func injectObjectMeta(t *metaV1.ObjectMeta, k8sLabels map[string]string, options
for k, v := range k8sLabels {
t.Labels[k] = v
}
return true
}
/* Given a PodSpec, update the PodSpec in place with the sidecar
* and init-container injected. If the pod is unsuitable for having them
* injected, return false.
*/
func injectPodSpec(t *v1.PodSpec, identity k8s.TLSIdentity, controlPlaneDNSNameOverride string, options *injectOptions, report *injectReport) bool {
report.hostNetwork = t.HostNetwork
report.sidecar = healthcheck.HasExistingSidecars(t)
report.udp = checkUDPPorts(t)
// Skip injection if:
// 1) Pods with `hostNetwork: true` share a network namespace with the host.
// The init-container would destroy the iptables configuration on the host.
// OR
// 2) Known 3rd party sidecars already present.
if report.hostNetwork || report.sidecar {
return false
}
// injectPodSpec adds linkerd sidecars to the provided PodSpec.
func injectPodSpec(t *v1.PodSpec, identity k8s.TLSIdentity, controlPlaneDNSNameOverride string, options *injectOptions) {
f := false
inboundSkipPorts := append(options.ignoreInboundPorts, options.proxyControlPort, options.proxyMetricsPort)
@ -358,8 +333,6 @@ func injectPodSpec(t *v1.PodSpec, identity k8s.TLSIdentity, controlPlaneDNSNameO
}
t.InitContainers = append(t.InitContainers, initContainer)
}
return true
}
func (rt resourceTransformerInject) transform(bytes []byte, options *injectOptions) ([]byte, []injectReport, error) {
@ -394,8 +367,11 @@ func (rt resourceTransformerInject) transform(bytes []byte, options *injectOptio
ControllerNamespace: controlPlaneNamespace,
}
if injectPodSpec(conf.podSpec, identity, conf.dnsNameOverride, options, &report) &&
injectObjectMeta(conf.objectMeta, conf.k8sLabels, options, &report) {
report.update(conf.objectMeta, conf.podSpec)
if report.shouldInject() {
injectObjectMeta(conf.objectMeta, conf.k8sLabels, options)
injectPodSpec(conf.podSpec, identity, conf.dnsNameOverride, options)
var err error
output, err = yaml.Marshal(conf.obj)
if err != nil {
@ -508,19 +484,3 @@ func (resourceTransformerInject) generateReport(injectReports []injectReport, ou
// Trailing newline to separate from kubectl output if piping
output.Write([]byte("\n"))
}
func checkUDPPorts(t *v1.PodSpec) bool {
// Check for ports with `protocol: UDP`, which will not be routed by Linkerd
for _, container := range t.Containers {
for _, port := range container.Ports {
if port.Protocol == v1.ProtocolUDP {
return true
}
}
}
return false
}
func injectDisabled(t *metaV1.ObjectMeta) bool {
return t.GetAnnotations()[k8s.ProxyInjectAnnotation] == k8s.ProxyInjectDisabled
}

View File

@ -8,10 +8,11 @@ import (
"os"
"path/filepath"
"github.com/linkerd/linkerd2/pkg/healthcheck"
"github.com/linkerd/linkerd2/pkg/k8s"
appsV1 "k8s.io/api/apps/v1"
batchV1 "k8s.io/api/batch/v1"
"k8s.io/api/core/v1"
v1 "k8s.io/api/core/v1"
"k8s.io/api/extensions/v1beta1"
metaV1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
@ -44,8 +45,39 @@ type resourceConfig struct {
k8sLabels map[string]string
}
func (i injectReport) resName() string {
return fmt.Sprintf("%s/%s", i.kind, i.name)
func (r injectReport) resName() string {
return fmt.Sprintf("%s/%s", r.kind, r.name)
}
// update updates the report for the provided resources.
func (r *injectReport) update(m *metaV1.ObjectMeta, p *v1.PodSpec) {
r.injectDisabled = m.GetAnnotations()[k8s.ProxyInjectAnnotation] == k8s.ProxyInjectDisabled
r.hostNetwork = p.HostNetwork
r.sidecar = healthcheck.HasExistingSidecars(p)
r.udp = checkUDPPorts(p)
}
func checkUDPPorts(t *v1.PodSpec) bool {
// Check for ports with `protocol: UDP`, which will not be routed by Linkerd
for _, container := range t.Containers {
for _, port := range container.Ports {
if port.Protocol == v1.ProtocolUDP {
return true
}
}
}
return false
}
// shouldInject returns false if the resource should not be injected.
//
// Injection is skipped in the following situations
// - Injection is disabled by annotation
// - Pods with `hostNetwork: true` share a network namespace with the host.
// The init-container would destroy the iptables configuration on the host.
// - Known 3rd party sidecars already present.
func (r *injectReport) shouldInject() bool {
return !r.injectDisabled && !r.hostNetwork && !r.sidecar
}
// Returns the integer representation of os.Exit code; 0 on success and 1 on failure.