diff --git a/pkg/cloudprovider/providers/gce/gce_annotations.go b/pkg/cloudprovider/providers/gce/gce_annotations.go index d1eee2acd3c..37671aeb2a9 100644 --- a/pkg/cloudprovider/providers/gce/gce_annotations.go +++ b/pkg/cloudprovider/providers/gce/gce_annotations.go @@ -17,11 +17,16 @@ limitations under the License. package gce import ( + "fmt" + "strings" + "github.com/golang/glog" + "k8s.io/api/core/v1" ) type LoadBalancerType string +type NetworkTier string const ( // ServiceAnnotationLoadBalancerType is annotated on a service with type LoadBalancer @@ -39,6 +44,17 @@ const ( ServiceAnnotationILBBackendShare = "alpha.cloud.google.com/load-balancer-backend-share" // This annotation did not correctly specify "alpha", so both annotations will be checked. deprecatedServiceAnnotationILBBackendShare = "cloud.google.com/load-balancer-backend-share" + + // NetworkTierAnnotationKey is annotated on a Service object to indicate which + // network tier a GCP LB should use. The valid values are "Standard" and + // "Premium" (default). + NetworkTierAnnotationKey = "cloud.google.com/network-tier" + NetworkTierAnnotationStandard = "Standard" + NetworkTierAnnotationPremium = "Premium" + + NetworkTierStandard NetworkTier = NetworkTierAnnotationStandard + NetworkTierPremium NetworkTier = NetworkTierAnnotationPremium + NetworkTierDefault NetworkTier = NetworkTierPremium ) // GetLoadBalancerAnnotationType returns the type of GCP load balancer which should be assembled. @@ -77,3 +93,42 @@ func GetLoadBalancerAnnotationBackendShare(service *v1.Service) bool { return false } + +// GetServiceNetworkTier returns the network tier of GCP load balancer +// which should be assembled, and an error if the specified tier is not +// supported. +func GetServiceNetworkTier(service *v1.Service) (NetworkTier, error) { + l, ok := service.Annotations[NetworkTierAnnotationKey] + if !ok { + return NetworkTierDefault, nil + } + + v := NetworkTier(l) + switch v { + case NetworkTierStandard: + fallthrough + case NetworkTierPremium: + return v, nil + default: + return NetworkTierDefault, fmt.Errorf("unsupported network tier: %q", v) + } +} + +// ToGCEValue converts NetworkTier to a string that we can populate the +// NetworkTier field of GCE objects. +func (n NetworkTier) ToGCEValue() string { + return strings.ToUpper(string(n)) +} + +// NetworkTierGCEValueToType converts the value of the NetworkTier field of a +// GCE object to the NetworkTier type. +func NetworkTierGCEValueToType(s string) NetworkTier { + switch s { + case "STANDARD": + return NetworkTierStandard + case "PREMIUM": + return NetworkTierPremium + default: + return NetworkTier(s) + } +} diff --git a/pkg/cloudprovider/providers/gce/gce_annotations_test.go b/pkg/cloudprovider/providers/gce/gce_annotations_test.go new file mode 100644 index 00000000000..62aad6f4180 --- /dev/null +++ b/pkg/cloudprovider/providers/gce/gce_annotations_test.go @@ -0,0 +1,70 @@ +/* +Copyright 2017 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package gce + +import ( + "testing" + + "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + + "github.com/stretchr/testify/assert" +) + +func TestServiceNetworkTierAnnotationKey(t *testing.T) { + createTestService := func() *v1.Service { + return &v1.Service{ + ObjectMeta: metav1.ObjectMeta{ + UID: "randome-uid", + Name: "test-svc", + Namespace: "test-ns", + }, + } + } + + for testName, testCase := range map[string]struct { + annotations map[string]string + expectedTier NetworkTier + expectErr bool + }{ + "Use the default when the annotation does not exist": { + annotations: nil, + expectedTier: NetworkTierDefault, + }, + "Standard tier": { + annotations: map[string]string{NetworkTierAnnotationKey: "Standard"}, + expectedTier: NetworkTierStandard, + }, + "Premium tier": { + annotations: map[string]string{NetworkTierAnnotationKey: "Premium"}, + expectedTier: NetworkTierPremium, + }, + "Report an error on invalid network tier value": { + annotations: map[string]string{NetworkTierAnnotationKey: "Unknown-tier"}, + expectedTier: NetworkTierPremium, + expectErr: true, + }, + } { + t.Run(testName, func(t *testing.T) { + svc := createTestService() + svc.Annotations = testCase.annotations + actualTier, err := GetServiceNetworkTier(svc) + assert.Equal(t, testCase.expectedTier, actualTier) + assert.Equal(t, testCase.expectErr, err != nil) + }) + } +}