From f5bd3938b8b6eb823bdc6a1b22813941c3dba13f Mon Sep 17 00:00:00 2001 From: Zihong Zheng Date: Wed, 2 May 2018 18:55:30 -0700 Subject: [PATCH] Add util functions for backendConfig annotation --- pkg/annotations/service.go | 31 +++++++++++ pkg/annotations/service_test.go | 97 +++++++++++++++++++++++++++++++++ 2 files changed, 128 insertions(+) diff --git a/pkg/annotations/service.go b/pkg/annotations/service.go index 0570482f42..d09a4205a8 100644 --- a/pkg/annotations/service.go +++ b/pkg/annotations/service.go @@ -40,6 +40,15 @@ const ( // 3. Adding this annotation on ingress. NetworkEndpointGroupAlphaAnnotation = "alpha.cloud.google.com/load-balancer-neg" + // BackendConfigKey is a stringified JSON with two fields: + // - "ports": a map of port names or port numbers to backendConfig names + // - "default": denotes the default backendConfig name for all ports except + // those are explicitly referenced. + // Examples: + // - '{"ports":{"my-https-port":"config-https","my-http-port":"config-http"}}' + // - '{"default":"config-default","ports":{"my-https-port":"config-https"}}' + BackendConfigKey = "alpha.cloud.google.com/backend-config" + // ProtocolHTTP protocol for a service ProtocolHTTP AppProtocol = "HTTP" // ProtocolHTTPS protocol for a service @@ -93,3 +102,25 @@ func (svc Service) NEGEnabled() bool { v, ok := svc.v[NetworkEndpointGroupAlphaAnnotation] return ok && v == "true" } + +type BackendConfigs struct { + Default string `json:"default,omitempty"` + Ports map[string]string `json:"ports,omitempty"` +} + +// GetBackendConfigs returns BackendConfigs for the service. +func (svc Service) GetBackendConfigs() (*BackendConfigs, error) { + val, ok := svc.v[BackendConfigKey] + if !ok { + return nil, nil + } + + configs := BackendConfigs{} + if err := json.Unmarshal([]byte(val), &configs); err != nil { + return nil, err + } + if configs.Default == "" && len(configs.Ports) == 0 { + return nil, fmt.Errorf("no backendConfigs found in annotation: %v", val) + } + return &configs, nil +} diff --git a/pkg/annotations/service_test.go b/pkg/annotations/service_test.go index da58cb6397..8195c7d998 100644 --- a/pkg/annotations/service_test.go +++ b/pkg/annotations/service_test.go @@ -118,3 +118,100 @@ func TestService(t *testing.T) { } } } + +func TestBackendConfigs(t *testing.T) { + testcases := []struct { + desc string + svc *v1.Service + expectedConfigs *BackendConfigs + expectErr bool + }{ + { + desc: "no backendConfig annotation", + svc: &v1.Service{}, + }, + { + desc: "single backendConfig", + svc: &v1.Service{ + ObjectMeta: metav1.ObjectMeta{ + Annotations: map[string]string{ + BackendConfigKey: `{"ports":{"http": "config-http"}}`, + }, + }, + }, + expectedConfigs: &BackendConfigs{ + Ports: map[string]string{ + "http": "config-http", + }, + }, + }, + { + desc: "multiple backendConfigs", + svc: &v1.Service{ + ObjectMeta: metav1.ObjectMeta{ + Annotations: map[string]string{ + BackendConfigKey: `{"ports":{"http": "config-http", "https": "config-https"}}`, + }, + }, + }, + expectedConfigs: &BackendConfigs{ + Ports: map[string]string{ + "http": "config-http", + "https": "config-https", + }, + }, + }, { + desc: "multiple backendConfigs with default", + svc: &v1.Service{ + ObjectMeta: metav1.ObjectMeta{ + Annotations: map[string]string{ + BackendConfigKey: `{"default": "config-default", "ports":{"http": "config-http", "https": "config-https"}}`, + }, + }, + }, + expectedConfigs: &BackendConfigs{ + Default: "config-default", + Ports: map[string]string{ + "http": "config-http", + "https": "config-https", + }, + }, + }, + { + desc: "invalid backendConfig annotation", + svc: &v1.Service{ + ObjectMeta: metav1.ObjectMeta{ + Annotations: map[string]string{ + BackendConfigKey: `invalid`, + }, + }, + }, + expectErr: true, + }, + { + desc: "wrong field name in backendConfig annotation", + svc: &v1.Service{ + ObjectMeta: metav1.ObjectMeta{ + Annotations: map[string]string{ + BackendConfigKey: `{"portstypo":{"https": "config-https"}}`, + }, + }, + }, + expectErr: true, + }, + } + + for _, tc := range testcases { + svc := FromService(tc.svc) + configs, err := svc.GetBackendConfigs() + if tc.expectErr { + if err == nil { + t.Errorf("%s: for annotions %+v; svc.GetBackendConfigs() = %v, _; want _, error", tc.desc, svc.v, configs) + } + continue + } + if err != nil || !reflect.DeepEqual(configs, tc.expectedConfigs) { + t.Errorf("%s: for annotions %+v; svc.GetBackendConfigs() = %v, %v; want %v, nil", tc.desc, svc.v, configs, err, tc.expectedConfigs) + } + } +}