Check for Namespace level config override annotations (#3194)

* Check for Namespace level config override annotations
* Add unit tests for namespace level config overrides
* add integration test for namespace level config override
* use different namespace for override tests
* check resource requests for integration tests

Signed-off-by: Tarun Pothulapati <tarunpothulapati@outlook.com>
This commit is contained in:
Tarun Pothulapati 2019-08-15 09:31:44 +05:30 committed by Ivan Sim
parent 879650cef9
commit 242566ac7c
3 changed files with 142 additions and 5 deletions

View File

@ -537,7 +537,10 @@ func (conf *ResourceConfig) injectPodAnnotations(values *patch) {
}
func (conf *ResourceConfig) getOverride(annotation string) string {
return conf.pod.meta.Annotations[annotation]
if override := conf.pod.meta.Annotations[annotation]; override != "" {
return override
}
return conf.nsAnnotations[annotation]
}
func (conf *ResourceConfig) proxyImage() string {

View File

@ -75,9 +75,10 @@ func TestConfigAccessors(t *testing.T) {
configs := &config.All{Global: globalConfig, Proxy: proxyConfig}
var testCases = []struct {
id string
spec appsv1.DeploymentSpec
expected expectedProxyConfigs
id string
nsAnnotations map[string]string
spec appsv1.DeploymentSpec
expected expectedProxyConfigs
}{
{id: "use overrides",
spec: appsv1.DeploymentSpec{
@ -168,6 +169,58 @@ func TestConfigAccessors(t *testing.T) {
outboundSkipPorts: "9079",
},
},
{id: "use namespace overrides",
nsAnnotations: map[string]string{
k8s.ProxyDisableIdentityAnnotation: "true",
k8s.ProxyImageAnnotation: "gcr.io/linkerd-io/proxy",
k8s.ProxyImagePullPolicyAnnotation: "Always",
k8s.ProxyInitImageAnnotation: "gcr.io/linkerd-io/proxy-init",
k8s.ProxyControlPortAnnotation: "4000",
k8s.ProxyInboundPortAnnotation: "5000",
k8s.ProxyAdminPortAnnotation: "5001",
k8s.ProxyOutboundPortAnnotation: "5002",
k8s.ProxyIgnoreInboundPortsAnnotation: "4222,6222",
k8s.ProxyIgnoreOutboundPortsAnnotation: "8079,8080",
k8s.ProxyCPURequestAnnotation: "0.15",
k8s.ProxyMemoryRequestAnnotation: "120",
k8s.ProxyCPULimitAnnotation: "1.5",
k8s.ProxyMemoryLimitAnnotation: "256",
k8s.ProxyUIDAnnotation: "8500",
k8s.ProxyLogLevelAnnotation: "debug,linkerd2_proxy=debug",
k8s.ProxyEnableExternalProfilesAnnotation: "false",
k8s.ProxyVersionOverrideAnnotation: proxyVersionOverride},
spec: appsv1.DeploymentSpec{
Template: corev1.PodTemplateSpec{
Spec: corev1.PodSpec{},
},
},
expected: expectedProxyConfigs{
image: "gcr.io/linkerd-io/proxy",
imagePullPolicy: "Always",
proxyVersion: proxyVersionOverride,
controlPort: int32(4000),
inboundPort: int32(5000),
adminPort: int32(5001),
outboundPort: int32(5002),
logLevel: "debug,linkerd2_proxy=debug",
resourceRequirements: &charts.Resources{
CPU: charts.Constraints{
Limit: "1500m",
Request: "150m",
},
Memory: charts.Constraints{
Limit: "256",
Request: "120",
},
},
proxyUID: int64(8500),
initImage: "gcr.io/linkerd-io/proxy-init",
initImagePullPolicy: "Always",
initVersion: version.ProxyInitVersion,
inboundSkipPorts: "4222,6222",
outboundSkipPorts: "8079,8080",
},
},
}
for _, tc := range testCases {
@ -178,7 +231,7 @@ func TestConfigAccessors(t *testing.T) {
t.Fatal(err)
}
resourceConfig := NewResourceConfig(configs, OriginUnknown).WithKind("Deployment")
resourceConfig := NewResourceConfig(configs, OriginUnknown).WithKind("Deployment").WithNsAnnotations(testCase.nsAnnotations)
if err := resourceConfig.parse(data); err != nil {
t.Fatal(err)
}

View File

@ -6,6 +6,9 @@ import (
"strings"
"testing"
v1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/api/resource"
jsonpatch "github.com/evanphx/json-patch"
"github.com/linkerd/linkerd2/pkg/k8s"
"github.com/linkerd/linkerd2/pkg/version"
@ -89,6 +92,72 @@ func TestInjectParams(t *testing.T) {
}
}
func TestNamespaceOverrideAnnotations(t *testing.T) {
// Check for Namespace level override of proxy Configurations
injectYAML, err := testutil.ReadFile("testdata/inject_test.yaml")
if err != nil {
t.Fatalf("failed to read inject test file: %s", err)
}
injectNS := "inject-namespace-override-test"
deployName := "inject-test-terminus"
nsProxyMemReq := "50Mi"
nsProxyCPUReq := "200m"
// Namespace level proxy configuration override
nsAnnotations := map[string]string{
k8s.ProxyInjectAnnotation: k8s.ProxyInjectEnabled,
k8s.ProxyCPURequestAnnotation: nsProxyCPUReq,
k8s.ProxyMemoryRequestAnnotation: nsProxyMemReq,
}
ns := TestHelper.GetTestNamespace(injectNS)
err = TestHelper.CreateNamespaceIfNotExists(ns, nsAnnotations)
if err != nil {
t.Fatalf("failed to create %s namespace: %s", ns, err)
}
// patch injectYAML with unique name and pod annotations
// Pod Level proxy configuration override
podProxyCPUReq := "600m"
podAnnotations := map[string]string{
k8s.ProxyCPURequestAnnotation: podProxyCPUReq,
}
patchedYAML, err := patchDeploy(injectYAML, deployName, podAnnotations)
if err != nil {
t.Fatalf("failed to patch inject test YAML in namespace %s for deploy/%s: %s", ns, deployName, err)
}
o, err := TestHelper.Kubectl(patchedYAML, "--namespace", ns, "create", "-f", "-")
if err != nil {
t.Fatalf("failed to create deploy/%s in namespace %s for %s: %s", deployName, ns, err, o)
}
o, err = TestHelper.Kubectl("", "--namespace", ns, "wait", "--for=condition=available", "--timeout=30s", "deploy/"+deployName)
if err != nil {
t.Fatalf("failed to wait for condition=available for deploy/%s in namespace %s: %s: %s", deployName, ns, err, o)
}
pods, err := TestHelper.GetPodsForDeployment(ns, deployName)
if err != nil {
t.Fatalf("failed to get pods for namespace %s: %s", ns, err)
}
containers := pods[0].Spec.Containers
proxyContainer := getProxyContainer(containers)
// Match the pod configuration with the namespace level overrides
if proxyContainer.Resources.Requests["memory"] != resource.MustParse(nsProxyMemReq) {
t.Fatalf("proxy memory resource request falied to match with namespace level override")
}
// Match with proxy level override
if proxyContainer.Resources.Requests["cpu"] != resource.MustParse(podProxyCPUReq) {
t.Fatalf("proxy cpu resource request falied to match with pod level override")
}
}
func TestAnnotationPermutations(t *testing.T) {
injectYAML, err := testutil.ReadFile("testdata/inject_test.yaml")
if err != nil {
@ -287,3 +356,15 @@ func validateInject(actual, fixtureFile string) error {
return nil
}
// Get Proxy Container from Containers
func getProxyContainer(containers []v1.Container) *v1.Container {
for _, c := range containers {
container := c
if container.Name == k8s.ProxyContainerName {
return &container
}
}
return nil
}