mirror of
https://github.com/ceph/ceph-csi.git
synced 2025-06-14 10:53:34 +00:00
vendor updates
This commit is contained in:
20
vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/BUILD
generated
vendored
20
vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/BUILD
generated
vendored
@ -23,7 +23,6 @@ go_library(
|
||||
"gce_disks.go",
|
||||
"gce_firewall.go",
|
||||
"gce_forwardingrule.go",
|
||||
"gce_forwardingrule_fakes.go",
|
||||
"gce_healthchecks.go",
|
||||
"gce_instancegroup.go",
|
||||
"gce_instances.go",
|
||||
@ -37,17 +36,23 @@ go_library(
|
||||
"gce_routes.go",
|
||||
"gce_targetpool.go",
|
||||
"gce_targetproxy.go",
|
||||
"gce_tpu.go",
|
||||
"gce_urlmap.go",
|
||||
"gce_util.go",
|
||||
"gce_zones.go",
|
||||
"metrics.go",
|
||||
"support.go",
|
||||
"token_source.go",
|
||||
],
|
||||
importpath = "k8s.io/kubernetes/pkg/cloudprovider/providers/gce",
|
||||
deps = [
|
||||
"//pkg/api/v1/service:go_default_library",
|
||||
"//pkg/cloudprovider:go_default_library",
|
||||
"//pkg/cloudprovider/providers/gce/cloud:go_default_library",
|
||||
"//pkg/cloudprovider/providers/gce/cloud/filter:go_default_library",
|
||||
"//pkg/cloudprovider/providers/gce/cloud/meta:go_default_library",
|
||||
"//pkg/controller:go_default_library",
|
||||
"//pkg/features:go_default_library",
|
||||
"//pkg/kubelet/apis:go_default_library",
|
||||
"//pkg/master/ports:go_default_library",
|
||||
"//pkg/util/net/sets:go_default_library",
|
||||
@ -65,6 +70,7 @@ go_library(
|
||||
"//vendor/google.golang.org/api/compute/v1:go_default_library",
|
||||
"//vendor/google.golang.org/api/container/v1:go_default_library",
|
||||
"//vendor/google.golang.org/api/googleapi:go_default_library",
|
||||
"//vendor/google.golang.org/api/tpu/v1alpha1:go_default_library",
|
||||
"//vendor/gopkg.in/gcfg.v1:go_default_library",
|
||||
"//vendor/k8s.io/api/core/v1:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/api/resource:go_default_library",
|
||||
@ -76,6 +82,7 @@ go_library(
|
||||
"//vendor/k8s.io/apimachinery/pkg/util/sets:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/util/wait:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/watch:go_default_library",
|
||||
"//vendor/k8s.io/apiserver/pkg/util/feature:go_default_library",
|
||||
"//vendor/k8s.io/client-go/informers:go_default_library",
|
||||
"//vendor/k8s.io/client-go/kubernetes:go_default_library",
|
||||
"//vendor/k8s.io/client-go/kubernetes/scheme:go_default_library",
|
||||
@ -98,10 +105,11 @@ go_test(
|
||||
"gce_util_test.go",
|
||||
"metrics_test.go",
|
||||
],
|
||||
importpath = "k8s.io/kubernetes/pkg/cloudprovider/providers/gce",
|
||||
library = ":go_default_library",
|
||||
embed = [":go_default_library"],
|
||||
deps = [
|
||||
"//pkg/cloudprovider:go_default_library",
|
||||
"//pkg/cloudprovider/providers/gce/cloud:go_default_library",
|
||||
"//pkg/cloudprovider/providers/gce/cloud/mock:go_default_library",
|
||||
"//pkg/kubelet/apis:go_default_library",
|
||||
"//vendor/github.com/stretchr/testify/assert:go_default_library",
|
||||
"//vendor/github.com/stretchr/testify/require:go_default_library",
|
||||
@ -112,6 +120,7 @@ go_test(
|
||||
"//vendor/google.golang.org/api/googleapi:go_default_library",
|
||||
"//vendor/k8s.io/api/core/v1:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/types:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/util/sets:go_default_library",
|
||||
],
|
||||
)
|
||||
@ -125,6 +134,9 @@ filegroup(
|
||||
|
||||
filegroup(
|
||||
name = "all-srcs",
|
||||
srcs = [":package-srcs"],
|
||||
srcs = [
|
||||
":package-srcs",
|
||||
"//pkg/cloudprovider/providers/gce/cloud:all-srcs",
|
||||
],
|
||||
tags = ["automanaged"],
|
||||
)
|
||||
|
64
vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud/BUILD
generated
vendored
Normal file
64
vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud/BUILD
generated
vendored
Normal file
@ -0,0 +1,64 @@
|
||||
load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test")
|
||||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = [
|
||||
"constants.go",
|
||||
"doc.go",
|
||||
"gce_projects.go",
|
||||
"gen.go",
|
||||
"op.go",
|
||||
"project.go",
|
||||
"ratelimit.go",
|
||||
"service.go",
|
||||
"utils.go",
|
||||
],
|
||||
importpath = "k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud",
|
||||
visibility = ["//visibility:public"],
|
||||
deps = [
|
||||
"//pkg/cloudprovider/providers/gce/cloud/filter:go_default_library",
|
||||
"//pkg/cloudprovider/providers/gce/cloud/meta:go_default_library",
|
||||
"//vendor/github.com/golang/glog:go_default_library",
|
||||
"//vendor/google.golang.org/api/compute/v0.alpha:go_default_library",
|
||||
"//vendor/google.golang.org/api/compute/v0.beta:go_default_library",
|
||||
"//vendor/google.golang.org/api/compute/v1:go_default_library",
|
||||
"//vendor/google.golang.org/api/googleapi:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
go_test(
|
||||
name = "go_default_test",
|
||||
srcs = [
|
||||
"gen_test.go",
|
||||
"mock_test.go",
|
||||
"utils_test.go",
|
||||
],
|
||||
embed = [":go_default_library"],
|
||||
deps = [
|
||||
"//pkg/cloudprovider/providers/gce/cloud/filter:go_default_library",
|
||||
"//pkg/cloudprovider/providers/gce/cloud/meta:go_default_library",
|
||||
"//vendor/google.golang.org/api/compute/v0.alpha:go_default_library",
|
||||
"//vendor/google.golang.org/api/compute/v0.beta:go_default_library",
|
||||
"//vendor/google.golang.org/api/compute/v1:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "package-srcs",
|
||||
srcs = glob(["**"]),
|
||||
tags = ["automanaged"],
|
||||
visibility = ["//visibility:private"],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "all-srcs",
|
||||
srcs = [
|
||||
":package-srcs",
|
||||
"//pkg/cloudprovider/providers/gce/cloud/filter:all-srcs",
|
||||
"//pkg/cloudprovider/providers/gce/cloud/gen:all-srcs",
|
||||
"//pkg/cloudprovider/providers/gce/cloud/meta:all-srcs",
|
||||
"//pkg/cloudprovider/providers/gce/cloud/mock:all-srcs",
|
||||
],
|
||||
tags = ["automanaged"],
|
||||
visibility = ["//visibility:public"],
|
||||
)
|
55
vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud/constants.go
generated
vendored
Normal file
55
vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud/constants.go
generated
vendored
Normal file
@ -0,0 +1,55 @@
|
||||
/*
|
||||
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 cloud
|
||||
|
||||
import (
|
||||
"strings"
|
||||
)
|
||||
|
||||
// NetworkTier represents the Network Service Tier used by a resource
|
||||
type NetworkTier string
|
||||
|
||||
// LbScheme represents the possible types of load balancers
|
||||
type LbScheme string
|
||||
|
||||
const (
|
||||
NetworkTierStandard NetworkTier = "Standard"
|
||||
NetworkTierPremium NetworkTier = "Premium"
|
||||
NetworkTierDefault NetworkTier = NetworkTierPremium
|
||||
|
||||
SchemeExternal LbScheme = "EXTERNAL"
|
||||
SchemeInternal LbScheme = "INTERNAL"
|
||||
)
|
||||
|
||||
// ToGCEValue converts NetworkTier to a string that we can populate the
|
||||
// NetworkTier field of GCE objects, including ForwardingRules and Addresses.
|
||||
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 NetworkTierStandard.ToGCEValue():
|
||||
return NetworkTierStandard
|
||||
case NetworkTierPremium.ToGCEValue():
|
||||
return NetworkTierPremium
|
||||
default:
|
||||
return NetworkTier(s)
|
||||
}
|
||||
}
|
112
vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud/doc.go
generated
vendored
Normal file
112
vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud/doc.go
generated
vendored
Normal file
@ -0,0 +1,112 @@
|
||||
/*
|
||||
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 cloud implements a more golang friendly interface to the GCE compute
|
||||
// API. The code in this package is generated automatically via the generator
|
||||
// implemented in "gen/main.go". The code generator creates the basic CRUD
|
||||
// actions for the given resource: "Insert", "Get", "List" and "Delete".
|
||||
// Additional methods by customizing the ServiceInfo object (see below).
|
||||
// Generated code includes a full mock of the GCE compute API.
|
||||
//
|
||||
// Usage
|
||||
//
|
||||
// The root of the GCE compute API is the interface "Cloud". Code written using
|
||||
// Cloud can be used against the actual implementation "GCE" or "MockGCE".
|
||||
//
|
||||
// func foo(cloud Cloud) {
|
||||
// igs, err := cloud.InstanceGroups().List(ctx, "us-central1-b", filter.None)
|
||||
// ...
|
||||
// }
|
||||
// // Run foo against the actual cloud.
|
||||
// foo(NewGCE(&Service{...}))
|
||||
// // Run foo with a mock.
|
||||
// foo(NewMockGCE())
|
||||
//
|
||||
// Rate limiting and routing
|
||||
//
|
||||
// The generated code allows for custom policies for operation rate limiting
|
||||
// and GCE project routing. See RateLimiter and ProjectRouter for more details.
|
||||
//
|
||||
// Mocks
|
||||
//
|
||||
// Mocks are automatically generated for each type implementing basic logic for
|
||||
// resource manipulation. This eliminates the boilerplate required to mock GCE
|
||||
// functionality. Each method will also have a corresponding "xxxHook"
|
||||
// function generated in the mock structure where unit test code can hook the
|
||||
// execution of the method.
|
||||
//
|
||||
// Mocks for different versions of the same service will share the same set of
|
||||
// objects, i.e. an alpha object will be visible with beta and GA methods.
|
||||
// Note that translation is done with JSON serialization between the API versions.
|
||||
//
|
||||
// Changing service code generation
|
||||
//
|
||||
// The list of services to generate is contained in "meta/meta.go". To add a
|
||||
// service, add an entry to the list "meta.AllServices". An example entry:
|
||||
//
|
||||
// &ServiceInfo{
|
||||
// Object: "InstanceGroup", // Name of the object type.
|
||||
// Service: "InstanceGroups", // Name of the service.
|
||||
// Resource: "instanceGroups", // Lowercase resource name (as appears in the URL).
|
||||
// version: meta.VersionAlpha, // API version (one entry per version is needed).
|
||||
// keyType: Zonal, // What kind of resource this is.
|
||||
// serviceType: reflect.TypeOf(&alpha.InstanceGroupsService{}), // Associated golang type.
|
||||
// additionalMethods: []string{ // Additional methods to generate code for.
|
||||
// "SetNamedPorts",
|
||||
// },
|
||||
// options: <options> // Or'd ("|") together.
|
||||
// }
|
||||
//
|
||||
// Read-only objects
|
||||
//
|
||||
// Services such as Regions and Zones do not allow for mutations. Specify
|
||||
// "ReadOnly" in ServiceInfo.options to omit the mutation methods.
|
||||
//
|
||||
// Adding custom methods
|
||||
//
|
||||
// Some methods that may not be properly handled by the generated code. To enable
|
||||
// addition of custom code to the generated mocks, set the "CustomOps" option
|
||||
// in "meta.ServiceInfo" entry. This will make the generated service interface
|
||||
// embed a "<ServiceName>Ops" interface. This interface MUST be written by hand
|
||||
// and contain the custom method logic. Corresponding methods must be added to
|
||||
// the corresponding Mockxxx and GCExxx struct types.
|
||||
//
|
||||
// // In "meta/meta.go":
|
||||
// &ServiceInfo{
|
||||
// Object: "InstanceGroup",
|
||||
// ...
|
||||
// options: CustomOps,
|
||||
// }
|
||||
//
|
||||
// // In the generated code "gen.go":
|
||||
// type InstanceGroups interface {
|
||||
// InstanceGroupsOps // Added by CustomOps option.
|
||||
// ...
|
||||
// }
|
||||
//
|
||||
// // In hand written file:
|
||||
// type InstanceGroupsOps interface {
|
||||
// MyMethod()
|
||||
// }
|
||||
//
|
||||
// func (mock *MockInstanceGroups) MyMethod() {
|
||||
// // Custom mock implementation.
|
||||
// }
|
||||
//
|
||||
// func (gce *GCEInstanceGroups) MyMethod() {
|
||||
// // Custom implementation.
|
||||
// }
|
||||
package cloud
|
29
vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud/filter/BUILD
generated
vendored
Normal file
29
vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud/filter/BUILD
generated
vendored
Normal file
@ -0,0 +1,29 @@
|
||||
load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test")
|
||||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = ["filter.go"],
|
||||
importpath = "k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud/filter",
|
||||
visibility = ["//visibility:public"],
|
||||
deps = ["//vendor/github.com/golang/glog:go_default_library"],
|
||||
)
|
||||
|
||||
go_test(
|
||||
name = "go_default_test",
|
||||
srcs = ["filter_test.go"],
|
||||
embed = [":go_default_library"],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "package-srcs",
|
||||
srcs = glob(["**"]),
|
||||
tags = ["automanaged"],
|
||||
visibility = ["//visibility:private"],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "all-srcs",
|
||||
srcs = [":package-srcs"],
|
||||
tags = ["automanaged"],
|
||||
visibility = ["//visibility:public"],
|
||||
)
|
303
vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud/filter/filter.go
generated
vendored
Normal file
303
vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud/filter/filter.go
generated
vendored
Normal file
@ -0,0 +1,303 @@
|
||||
/*
|
||||
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 filter encapsulates the filter argument to compute API calls.
|
||||
//
|
||||
// // List all global addresses (no filter).
|
||||
// c.GlobalAddresses().List(ctx, filter.None)
|
||||
//
|
||||
// // List global addresses filtering for name matching "abc.*".
|
||||
// c.GlobalAddresses().List(ctx, filter.Regexp("name", "abc.*"))
|
||||
//
|
||||
// // List on multiple conditions.
|
||||
// f := filter.Regexp("name", "homer.*").AndNotRegexp("name", "homers")
|
||||
// c.GlobalAddresses().List(ctx, f)
|
||||
package filter
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"reflect"
|
||||
"regexp"
|
||||
"strings"
|
||||
|
||||
"github.com/golang/glog"
|
||||
)
|
||||
|
||||
var (
|
||||
// None indicates that the List result set should not be filter (i.e.
|
||||
// return all values).
|
||||
None *F
|
||||
)
|
||||
|
||||
// Regexp returns a filter for fieldName matches regexp v.
|
||||
func Regexp(fieldName, v string) *F {
|
||||
return (&F{}).AndRegexp(fieldName, v)
|
||||
}
|
||||
|
||||
// NotRegexp returns a filter for fieldName not matches regexp v.
|
||||
func NotRegexp(fieldName, v string) *F {
|
||||
return (&F{}).AndNotRegexp(fieldName, v)
|
||||
}
|
||||
|
||||
// EqualInt returns a filter for fieldName ~ v.
|
||||
func EqualInt(fieldName string, v int) *F {
|
||||
return (&F{}).AndEqualInt(fieldName, v)
|
||||
}
|
||||
|
||||
// NotEqualInt returns a filter for fieldName != v.
|
||||
func NotEqualInt(fieldName string, v int) *F {
|
||||
return (&F{}).AndNotEqualInt(fieldName, v)
|
||||
}
|
||||
|
||||
// EqualBool returns a filter for fieldName == v.
|
||||
func EqualBool(fieldName string, v bool) *F {
|
||||
return (&F{}).AndEqualBool(fieldName, v)
|
||||
}
|
||||
|
||||
// NotEqualBool returns a filter for fieldName != v.
|
||||
func NotEqualBool(fieldName string, v bool) *F {
|
||||
return (&F{}).AndNotEqualBool(fieldName, v)
|
||||
}
|
||||
|
||||
// F is a filter to be used with List() operations.
|
||||
//
|
||||
// From the compute API description:
|
||||
//
|
||||
// Sets a filter {expression} for filtering listed resources. Your {expression}
|
||||
// must be in the format: field_name comparison_string literal_string.
|
||||
//
|
||||
// The field_name is the name of the field you want to compare. Only atomic field
|
||||
// types are supported (string, number, boolean). The comparison_string must be
|
||||
// either eq (equals) or ne (not equals). The literal_string is the string value
|
||||
// to filter to. The literal value must be valid for the type of field you are
|
||||
// filtering by (string, number, boolean). For string fields, the literal value is
|
||||
// interpreted as a regular expression using RE2 syntax. The literal value must
|
||||
// match the entire field.
|
||||
//
|
||||
// For example, to filter for instances that do not have a name of
|
||||
// example-instance, you would use name ne example-instance.
|
||||
//
|
||||
// You can filter on nested fields. For example, you could filter on instances
|
||||
// that have set the scheduling.automaticRestart field to true. Use filtering on
|
||||
// nested fields to take advantage of labels to organize and search for results
|
||||
// based on label values.
|
||||
//
|
||||
// To filter on multiple expressions, provide each separate expression within
|
||||
// parentheses. For example, (scheduling.automaticRestart eq true)
|
||||
// (zone eq us-central1-f). Multiple expressions are treated as AND expressions,
|
||||
// meaning that resources must match all expressions to pass the filters.
|
||||
type F struct {
|
||||
predicates []filterPredicate
|
||||
}
|
||||
|
||||
// And joins two filters together.
|
||||
func (fl *F) And(rest *F) *F {
|
||||
fl.predicates = append(fl.predicates, rest.predicates...)
|
||||
return fl
|
||||
}
|
||||
|
||||
// AndRegexp adds a field match string predicate.
|
||||
func (fl *F) AndRegexp(fieldName, v string) *F {
|
||||
fl.predicates = append(fl.predicates, filterPredicate{fieldName: fieldName, op: equals, s: &v})
|
||||
return fl
|
||||
}
|
||||
|
||||
// AndNotRegexp adds a field not match string predicate.
|
||||
func (fl *F) AndNotRegexp(fieldName, v string) *F {
|
||||
fl.predicates = append(fl.predicates, filterPredicate{fieldName: fieldName, op: notEquals, s: &v})
|
||||
return fl
|
||||
}
|
||||
|
||||
// AndEqualInt adds a field == int predicate.
|
||||
func (fl *F) AndEqualInt(fieldName string, v int) *F {
|
||||
fl.predicates = append(fl.predicates, filterPredicate{fieldName: fieldName, op: equals, i: &v})
|
||||
return fl
|
||||
}
|
||||
|
||||
// AndNotEqualInt adds a field != int predicate.
|
||||
func (fl *F) AndNotEqualInt(fieldName string, v int) *F {
|
||||
fl.predicates = append(fl.predicates, filterPredicate{fieldName: fieldName, op: notEquals, i: &v})
|
||||
return fl
|
||||
}
|
||||
|
||||
// AndEqualBool adds a field == bool predicate.
|
||||
func (fl *F) AndEqualBool(fieldName string, v bool) *F {
|
||||
fl.predicates = append(fl.predicates, filterPredicate{fieldName: fieldName, op: equals, b: &v})
|
||||
return fl
|
||||
}
|
||||
|
||||
// AndNotEqualBool adds a field != bool predicate.
|
||||
func (fl *F) AndNotEqualBool(fieldName string, v bool) *F {
|
||||
fl.predicates = append(fl.predicates, filterPredicate{fieldName: fieldName, op: notEquals, b: &v})
|
||||
return fl
|
||||
}
|
||||
|
||||
func (fl *F) String() string {
|
||||
if len(fl.predicates) == 1 {
|
||||
return fl.predicates[0].String()
|
||||
}
|
||||
|
||||
var pl []string
|
||||
for _, p := range fl.predicates {
|
||||
pl = append(pl, "("+p.String()+")")
|
||||
}
|
||||
return strings.Join(pl, " ")
|
||||
}
|
||||
|
||||
// Match returns true if the F as specifies matches the given object. This
|
||||
// is used by the Mock implementations to perform filtering and SHOULD NOT be
|
||||
// used in production code as it is not well-tested to be equivalent to the
|
||||
// actual compute API.
|
||||
func (fl *F) Match(obj interface{}) bool {
|
||||
if fl == nil {
|
||||
return true
|
||||
}
|
||||
for _, p := range fl.predicates {
|
||||
if !p.match(obj) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
type filterOp int
|
||||
|
||||
const (
|
||||
equals filterOp = iota
|
||||
notEquals filterOp = iota
|
||||
)
|
||||
|
||||
// filterPredicate is an individual predicate for a fieldName and value.
|
||||
type filterPredicate struct {
|
||||
fieldName string
|
||||
|
||||
op filterOp
|
||||
s *string
|
||||
i *int
|
||||
b *bool
|
||||
}
|
||||
|
||||
func (fp *filterPredicate) String() string {
|
||||
var op string
|
||||
switch fp.op {
|
||||
case equals:
|
||||
op = "eq"
|
||||
case notEquals:
|
||||
op = "ne"
|
||||
default:
|
||||
op = "invalidOp"
|
||||
}
|
||||
|
||||
var value string
|
||||
switch {
|
||||
case fp.s != nil:
|
||||
// There does not seem to be any sort of escaping as specified in the
|
||||
// document. This means it's possible to create malformed expressions.
|
||||
value = *fp.s
|
||||
case fp.i != nil:
|
||||
value = fmt.Sprintf("%d", *fp.i)
|
||||
case fp.b != nil:
|
||||
value = fmt.Sprintf("%t", *fp.b)
|
||||
default:
|
||||
value = "invalidValue"
|
||||
}
|
||||
|
||||
return fmt.Sprintf("%s %s %s", fp.fieldName, op, value)
|
||||
}
|
||||
|
||||
func (fp *filterPredicate) match(o interface{}) bool {
|
||||
v, err := extractValue(fp.fieldName, o)
|
||||
glog.V(6).Infof("extractValue(%q, %#v) = %v, %v", fp.fieldName, o, v, err)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
|
||||
var match bool
|
||||
switch x := v.(type) {
|
||||
case string:
|
||||
if fp.s == nil {
|
||||
return false
|
||||
}
|
||||
re, err := regexp.Compile(*fp.s)
|
||||
if err != nil {
|
||||
glog.Errorf("Match regexp %q is invalid: %v", *fp.s, err)
|
||||
return false
|
||||
}
|
||||
match = re.Match([]byte(x))
|
||||
case int:
|
||||
if fp.i == nil {
|
||||
return false
|
||||
}
|
||||
match = x == *fp.i
|
||||
case bool:
|
||||
if fp.b == nil {
|
||||
return false
|
||||
}
|
||||
match = x == *fp.b
|
||||
}
|
||||
|
||||
switch fp.op {
|
||||
case equals:
|
||||
return match
|
||||
case notEquals:
|
||||
return !match
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
// snakeToCamelCase converts from "names_like_this" to "NamesLikeThis" to
|
||||
// interoperate between proto and Golang naming conventions.
|
||||
func snakeToCamelCase(s string) string {
|
||||
parts := strings.Split(s, "_")
|
||||
var ret string
|
||||
for _, x := range parts {
|
||||
ret += strings.Title(x)
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
// extractValue returns the value of the field named by path in object o if it exists.
|
||||
func extractValue(path string, o interface{}) (interface{}, error) {
|
||||
parts := strings.Split(path, ".")
|
||||
for _, f := range parts {
|
||||
v := reflect.ValueOf(o)
|
||||
// Dereference Ptr to handle *struct.
|
||||
if v.Kind() == reflect.Ptr {
|
||||
if v.IsNil() {
|
||||
return nil, errors.New("field is nil")
|
||||
}
|
||||
v = v.Elem()
|
||||
}
|
||||
if v.Kind() != reflect.Struct {
|
||||
return nil, fmt.Errorf("cannot get field from non-struct (%T)", o)
|
||||
}
|
||||
v = v.FieldByName(snakeToCamelCase(f))
|
||||
if !v.IsValid() {
|
||||
return nil, fmt.Errorf("cannot get field %q as it is not a valid field in %T", f, o)
|
||||
}
|
||||
if !v.CanInterface() {
|
||||
return nil, fmt.Errorf("cannot get field %q in obj of type %T", f, o)
|
||||
}
|
||||
o = v.Interface()
|
||||
}
|
||||
switch o.(type) {
|
||||
case string, int, bool:
|
||||
return o, nil
|
||||
}
|
||||
return nil, fmt.Errorf("unhandled object of type %T", o)
|
||||
}
|
176
vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud/filter/filter_test.go
generated
vendored
Normal file
176
vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud/filter/filter_test.go
generated
vendored
Normal file
@ -0,0 +1,176 @@
|
||||
/*
|
||||
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 filter
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestFilterToString(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
for _, tc := range []struct {
|
||||
f *F
|
||||
want string
|
||||
}{
|
||||
{Regexp("field1", "abc"), `field1 eq abc`},
|
||||
{NotRegexp("field1", "abc"), `field1 ne abc`},
|
||||
{EqualInt("field1", 13), "field1 eq 13"},
|
||||
{NotEqualInt("field1", 13), "field1 ne 13"},
|
||||
{EqualBool("field1", true), "field1 eq true"},
|
||||
{NotEqualBool("field1", true), "field1 ne true"},
|
||||
{Regexp("field1", "abc").AndRegexp("field2", "def"), `(field1 eq abc) (field2 eq def)`},
|
||||
{Regexp("field1", "abc").AndNotEqualInt("field2", 17), `(field1 eq abc) (field2 ne 17)`},
|
||||
{Regexp("field1", "abc").And(EqualInt("field2", 17)), `(field1 eq abc) (field2 eq 17)`},
|
||||
} {
|
||||
if tc.f.String() != tc.want {
|
||||
t.Errorf("filter %#v String() = %q, want %q", tc.f, tc.f.String(), tc.want)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestFilterMatch(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
type inner struct {
|
||||
X string
|
||||
}
|
||||
type S struct {
|
||||
S string
|
||||
I int
|
||||
B bool
|
||||
Unhandled struct{}
|
||||
NestedField *inner
|
||||
}
|
||||
|
||||
for _, tc := range []struct {
|
||||
f *F
|
||||
o interface{}
|
||||
want bool
|
||||
}{
|
||||
{f: None, o: &S{}, want: true},
|
||||
{f: Regexp("s", "abc"), o: &S{}},
|
||||
{f: EqualInt("i", 10), o: &S{}},
|
||||
{f: EqualBool("b", true), o: &S{}},
|
||||
{f: NotRegexp("s", "abc"), o: &S{}, want: true},
|
||||
{f: NotEqualInt("i", 10), o: &S{}, want: true},
|
||||
{f: NotEqualBool("b", true), o: &S{}, want: true},
|
||||
{f: Regexp("s", "abc").AndEqualBool("b", true), o: &S{}},
|
||||
{f: Regexp("s", "abc"), o: &S{S: "abc"}, want: true},
|
||||
{f: Regexp("s", "a.*"), o: &S{S: "abc"}, want: true},
|
||||
{f: Regexp("s", "a((("), o: &S{S: "abc"}},
|
||||
{f: NotRegexp("s", "abc"), o: &S{S: "abc"}},
|
||||
{f: EqualInt("i", 10), o: &S{I: 11}},
|
||||
{f: EqualInt("i", 10), o: &S{I: 10}, want: true},
|
||||
{f: Regexp("s", "abc").AndEqualBool("b", true), o: &S{S: "abc"}},
|
||||
{f: Regexp("s", "abcd").AndEqualBool("b", true), o: &S{S: "abc"}},
|
||||
{f: Regexp("s", "abc").AndEqualBool("b", true), o: &S{S: "abc", B: true}, want: true},
|
||||
{f: Regexp("s", "abc").And(EqualBool("b", true)), o: &S{S: "abc", B: true}, want: true},
|
||||
{f: Regexp("unhandled", "xyz"), o: &S{}},
|
||||
{f: Regexp("nested_field.x", "xyz"), o: &S{}},
|
||||
{f: Regexp("nested_field.x", "xyz"), o: &S{NestedField: &inner{"xyz"}}, want: true},
|
||||
{f: NotRegexp("nested_field.x", "xyz"), o: &S{NestedField: &inner{"xyz"}}},
|
||||
{f: Regexp("nested_field.y", "xyz"), o: &S{NestedField: &inner{"xyz"}}},
|
||||
{f: Regexp("nested_field", "xyz"), o: &S{NestedField: &inner{"xyz"}}},
|
||||
} {
|
||||
got := tc.f.Match(tc.o)
|
||||
if got != tc.want {
|
||||
t.Errorf("%v: Match(%+v) = %v, want %v", tc.f, tc.o, got, tc.want)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestFilterSnakeToCamelCase(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
for _, tc := range []struct {
|
||||
s string
|
||||
want string
|
||||
}{
|
||||
{"", ""},
|
||||
{"abc", "Abc"},
|
||||
{"_foo", "Foo"},
|
||||
{"a_b_c", "ABC"},
|
||||
{"a_BC_def", "ABCDef"},
|
||||
{"a_Bc_def", "ABcDef"},
|
||||
} {
|
||||
got := snakeToCamelCase(tc.s)
|
||||
if got != tc.want {
|
||||
t.Errorf("snakeToCamelCase(%q) = %q, want %q", tc.s, got, tc.want)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestFilterExtractValue(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
type nest2 struct {
|
||||
Y string
|
||||
}
|
||||
type nest struct {
|
||||
X string
|
||||
Nest2 nest2
|
||||
}
|
||||
st := &struct {
|
||||
S string
|
||||
I int
|
||||
F bool
|
||||
Nest nest
|
||||
NestPtr *nest
|
||||
|
||||
Unhandled float64
|
||||
}{
|
||||
"abc",
|
||||
13,
|
||||
true,
|
||||
nest{"xyz", nest2{"zzz"}},
|
||||
&nest{"yyy", nest2{}},
|
||||
0.0,
|
||||
}
|
||||
|
||||
for _, tc := range []struct {
|
||||
path string
|
||||
o interface{}
|
||||
want interface{}
|
||||
wantErr bool
|
||||
}{
|
||||
{path: "s", o: st, want: "abc"},
|
||||
{path: "i", o: st, want: 13},
|
||||
{path: "f", o: st, want: true},
|
||||
{path: "nest.x", o: st, want: "xyz"},
|
||||
{path: "nest_ptr.x", o: st, want: "yyy"},
|
||||
// Error cases.
|
||||
{path: "", o: st, wantErr: true},
|
||||
{path: "no_such_field", o: st, wantErr: true},
|
||||
{path: "s.invalid_type", o: st, wantErr: true},
|
||||
{path: "unhandled", o: st, wantErr: true},
|
||||
{path: "nest.x", o: &struct{ Nest *nest }{}, wantErr: true},
|
||||
} {
|
||||
o, err := extractValue(tc.path, tc.o)
|
||||
gotErr := err != nil
|
||||
if gotErr != tc.wantErr {
|
||||
t.Errorf("extractValue(%v, %+v) = %v, %v; gotErr = %v, tc.wantErr = %v", tc.path, tc.o, o, err, gotErr, tc.wantErr)
|
||||
}
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
if !reflect.DeepEqual(o, tc.want) {
|
||||
t.Errorf("extractValue(%v, %+v) = %v, nil; want %v, nil", tc.path, tc.o, o, tc.want)
|
||||
}
|
||||
}
|
||||
}
|
99
vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud/gce_projects.go
generated
vendored
Normal file
99
vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud/gce_projects.go
generated
vendored
Normal file
@ -0,0 +1,99 @@
|
||||
/*
|
||||
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 cloud
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"net/http"
|
||||
|
||||
compute "google.golang.org/api/compute/v1"
|
||||
"google.golang.org/api/googleapi"
|
||||
"k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud/meta"
|
||||
)
|
||||
|
||||
// ProjectsOps is the manually implemented methods for the Projects service.
|
||||
type ProjectsOps interface {
|
||||
Get(ctx context.Context, projectID string) (*compute.Project, error)
|
||||
SetCommonInstanceMetadata(ctx context.Context, projectID string, m *compute.Metadata) error
|
||||
}
|
||||
|
||||
// MockProjectOpsState is stored in the mock.X field.
|
||||
type MockProjectOpsState struct {
|
||||
metadata map[string]*compute.Metadata
|
||||
}
|
||||
|
||||
// Get a project by projectID.
|
||||
func (m *MockProjects) Get(ctx context.Context, projectID string) (*compute.Project, error) {
|
||||
m.Lock.Lock()
|
||||
defer m.Lock.Unlock()
|
||||
|
||||
if p, ok := m.Objects[*meta.GlobalKey(projectID)]; ok {
|
||||
return p.ToGA(), nil
|
||||
}
|
||||
return nil, &googleapi.Error{
|
||||
Code: http.StatusNotFound,
|
||||
Message: fmt.Sprintf("MockProjects %v not found", projectID),
|
||||
}
|
||||
}
|
||||
|
||||
// Get a project by projectID.
|
||||
func (g *GCEProjects) Get(ctx context.Context, projectID string) (*compute.Project, error) {
|
||||
rk := &RateLimitKey{
|
||||
ProjectID: projectID,
|
||||
Operation: "Get",
|
||||
Version: meta.Version("ga"),
|
||||
Service: "Projects",
|
||||
}
|
||||
if err := g.s.RateLimiter.Accept(ctx, rk); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
call := g.s.GA.Projects.Get(projectID)
|
||||
call.Context(ctx)
|
||||
return call.Do()
|
||||
}
|
||||
|
||||
// SetCommonInstanceMetadata for a given project.
|
||||
func (m *MockProjects) SetCommonInstanceMetadata(ctx context.Context, projectID string, meta *compute.Metadata) error {
|
||||
if m.X == nil {
|
||||
m.X = &MockProjectOpsState{metadata: map[string]*compute.Metadata{}}
|
||||
}
|
||||
state := m.X.(*MockProjectOpsState)
|
||||
state.metadata[projectID] = meta
|
||||
return nil
|
||||
}
|
||||
|
||||
// SetCommonInstanceMetadata for a given project.
|
||||
func (g *GCEProjects) SetCommonInstanceMetadata(ctx context.Context, projectID string, m *compute.Metadata) error {
|
||||
rk := &RateLimitKey{
|
||||
ProjectID: projectID,
|
||||
Operation: "SetCommonInstanceMetadata",
|
||||
Version: meta.Version("ga"),
|
||||
Service: "Projects",
|
||||
}
|
||||
if err := g.s.RateLimiter.Accept(ctx, rk); err != nil {
|
||||
return err
|
||||
}
|
||||
call := g.s.GA.Projects.SetCommonInstanceMetadata(projectID, m)
|
||||
call.Context(ctx)
|
||||
|
||||
op, err := call.Do()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return g.s.WaitForCompletion(ctx, op)
|
||||
}
|
13154
vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud/gen.go
generated
vendored
Normal file
13154
vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud/gen.go
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
29
vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud/gen/BUILD
generated
vendored
Normal file
29
vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud/gen/BUILD
generated
vendored
Normal file
@ -0,0 +1,29 @@
|
||||
load("@io_bazel_rules_go//go:def.bzl", "go_binary", "go_library")
|
||||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = ["main.go"],
|
||||
importpath = "k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud/gen",
|
||||
visibility = ["//visibility:private"],
|
||||
deps = ["//pkg/cloudprovider/providers/gce/cloud/meta:go_default_library"],
|
||||
)
|
||||
|
||||
go_binary(
|
||||
name = "gen",
|
||||
embed = [":go_default_library"],
|
||||
visibility = ["//visibility:public"],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "package-srcs",
|
||||
srcs = glob(["**"]),
|
||||
tags = ["automanaged"],
|
||||
visibility = ["//visibility:private"],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "all-srcs",
|
||||
srcs = [":package-srcs"],
|
||||
tags = ["automanaged"],
|
||||
visibility = ["//visibility:public"],
|
||||
)
|
1277
vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud/gen/main.go
generated
vendored
Normal file
1277
vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud/gen/main.go
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
1809
vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud/gen_test.go
generated
vendored
Normal file
1809
vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud/gen_test.go
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
39
vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud/meta/BUILD
generated
vendored
Normal file
39
vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud/meta/BUILD
generated
vendored
Normal file
@ -0,0 +1,39 @@
|
||||
load("@io_bazel_rules_go//go:def.bzl", "go_library", "go_test")
|
||||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = [
|
||||
"doc.go",
|
||||
"key.go",
|
||||
"meta.go",
|
||||
"method.go",
|
||||
"service.go",
|
||||
],
|
||||
importpath = "k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud/meta",
|
||||
visibility = ["//visibility:public"],
|
||||
deps = [
|
||||
"//vendor/google.golang.org/api/compute/v0.alpha:go_default_library",
|
||||
"//vendor/google.golang.org/api/compute/v0.beta:go_default_library",
|
||||
"//vendor/google.golang.org/api/compute/v1:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
go_test(
|
||||
name = "go_default_test",
|
||||
srcs = ["key_test.go"],
|
||||
embed = [":go_default_library"],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "package-srcs",
|
||||
srcs = glob(["**"]),
|
||||
tags = ["automanaged"],
|
||||
visibility = ["//visibility:private"],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "all-srcs",
|
||||
srcs = [":package-srcs"],
|
||||
tags = ["automanaged"],
|
||||
visibility = ["//visibility:public"],
|
||||
)
|
19
vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud/meta/doc.go
generated
vendored
Normal file
19
vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud/meta/doc.go
generated
vendored
Normal file
@ -0,0 +1,19 @@
|
||||
/*
|
||||
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 meta contains the meta description of the GCE cloud types to
|
||||
// generate code for.
|
||||
package meta
|
108
vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud/meta/key.go
generated
vendored
Normal file
108
vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud/meta/key.go
generated
vendored
Normal file
@ -0,0 +1,108 @@
|
||||
/*
|
||||
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 meta
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"regexp"
|
||||
)
|
||||
|
||||
// Key for a GCP resource.
|
||||
type Key struct {
|
||||
Name string
|
||||
Zone string
|
||||
Region string
|
||||
}
|
||||
|
||||
// KeyType is the type of the key.
|
||||
type KeyType string
|
||||
|
||||
const (
|
||||
// Zonal key type.
|
||||
Zonal = "zonal"
|
||||
// Regional key type.
|
||||
Regional = "regional"
|
||||
// Global key type.
|
||||
Global = "global"
|
||||
)
|
||||
|
||||
var (
|
||||
// locationRegexp is the format of regions/zone names in GCE.
|
||||
locationRegexp = regexp.MustCompile("^[a-z](?:[-a-z0-9]+)?$")
|
||||
)
|
||||
|
||||
// ZonalKey returns the key for a zonal resource.
|
||||
func ZonalKey(name, zone string) *Key {
|
||||
return &Key{name, zone, ""}
|
||||
}
|
||||
|
||||
// RegionalKey returns the key for a regional resource.
|
||||
func RegionalKey(name, region string) *Key {
|
||||
return &Key{name, "", region}
|
||||
}
|
||||
|
||||
// GlobalKey returns the key for a global resource.
|
||||
func GlobalKey(name string) *Key {
|
||||
return &Key{name, "", ""}
|
||||
}
|
||||
|
||||
// Type returns the type of the key.
|
||||
func (k *Key) Type() KeyType {
|
||||
switch {
|
||||
case k.Zone != "":
|
||||
return Zonal
|
||||
case k.Region != "":
|
||||
return Regional
|
||||
default:
|
||||
return Global
|
||||
}
|
||||
}
|
||||
|
||||
// String returns a string representation of the key.
|
||||
func (k Key) String() string {
|
||||
switch k.Type() {
|
||||
case Zonal:
|
||||
return fmt.Sprintf("Key{%q, zone: %q}", k.Name, k.Zone)
|
||||
case Regional:
|
||||
return fmt.Sprintf("Key{%q, region: %q}", k.Name, k.Region)
|
||||
default:
|
||||
return fmt.Sprintf("Key{%q}", k.Name)
|
||||
}
|
||||
}
|
||||
|
||||
// Valid is true if the key is valid.
|
||||
func (k *Key) Valid() bool {
|
||||
if k.Zone != "" && k.Region != "" {
|
||||
return false
|
||||
}
|
||||
switch {
|
||||
case k.Region != "":
|
||||
return locationRegexp.Match([]byte(k.Region))
|
||||
case k.Zone != "":
|
||||
return locationRegexp.Match([]byte(k.Zone))
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// KeysToMap creates a map[Key]bool from a list of keys.
|
||||
func KeysToMap(keys ...Key) map[Key]bool {
|
||||
ret := map[Key]bool{}
|
||||
for _, k := range keys {
|
||||
ret[k] = true
|
||||
}
|
||||
return ret
|
||||
}
|
76
vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud/meta/key_test.go
generated
vendored
Normal file
76
vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud/meta/key_test.go
generated
vendored
Normal file
@ -0,0 +1,76 @@
|
||||
/*
|
||||
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 meta
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestKeyType(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
for _, tc := range []struct {
|
||||
key *Key
|
||||
want KeyType
|
||||
}{
|
||||
{GlobalKey("abc"), Global},
|
||||
{ZonalKey("abc", "us-central1-b"), Zonal},
|
||||
{RegionalKey("abc", "us-central1"), Regional},
|
||||
} {
|
||||
if tc.key.Type() != tc.want {
|
||||
t.Errorf("key.Type() == %v, want %v", tc.key.Type(), tc.want)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestKeyString(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
for _, k := range []*Key{
|
||||
GlobalKey("abc"),
|
||||
RegionalKey("abc", "us-central1"),
|
||||
ZonalKey("abc", "us-central1-b"),
|
||||
} {
|
||||
if k.String() == "" {
|
||||
t.Errorf(`k.String() = "", want non-empty`)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestKeyValid(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
region := "us-central1"
|
||||
zone := "us-central1-b"
|
||||
|
||||
for _, tc := range []struct {
|
||||
key *Key
|
||||
want bool
|
||||
}{
|
||||
{GlobalKey("abc"), true},
|
||||
{RegionalKey("abc", region), true},
|
||||
{ZonalKey("abc", zone), true},
|
||||
{RegionalKey("abc", "/invalid/"), false},
|
||||
{ZonalKey("abc", "/invalid/"), false},
|
||||
{&Key{"abc", zone, region}, false},
|
||||
} {
|
||||
got := tc.key.Valid()
|
||||
if got != tc.want {
|
||||
t.Errorf("key %+v; key.Valid() = %v, want %v", tc.key, got, tc.want)
|
||||
}
|
||||
}
|
||||
}
|
386
vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud/meta/meta.go
generated
vendored
Normal file
386
vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud/meta/meta.go
generated
vendored
Normal file
@ -0,0 +1,386 @@
|
||||
/*
|
||||
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 meta
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
|
||||
alpha "google.golang.org/api/compute/v0.alpha"
|
||||
beta "google.golang.org/api/compute/v0.beta"
|
||||
ga "google.golang.org/api/compute/v1"
|
||||
)
|
||||
|
||||
// Version of the API (ga, alpha, beta).
|
||||
type Version string
|
||||
|
||||
const (
|
||||
// NoGet prevents the Get() method from being generated.
|
||||
NoGet = 1 << iota
|
||||
// NoList prevents the List() method from being generated.
|
||||
NoList = 1 << iota
|
||||
// NoDelete prevents the Delete() method from being generated.
|
||||
NoDelete = 1 << iota
|
||||
// NoInsert prevents the Insert() method from being generated.
|
||||
NoInsert = 1 << iota
|
||||
// CustomOps specifies that an empty interface xxxOps will be generated to
|
||||
// enable custom method calls to be attached to the generated service
|
||||
// interface.
|
||||
CustomOps = 1 << iota
|
||||
// AggregatedList will generated a method for AggregatedList().
|
||||
AggregatedList = 1 << iota
|
||||
|
||||
// ReadOnly specifies that the given resource is read-only and should not
|
||||
// have insert() or delete() methods generated for the wrapper.
|
||||
ReadOnly = NoDelete | NoInsert
|
||||
|
||||
// VersionGA is the API version in compute.v1.
|
||||
VersionGA Version = "ga"
|
||||
// VersionAlpha is the API version in computer.v0.alpha.
|
||||
VersionAlpha Version = "alpha"
|
||||
// VersionBeta is the API version in computer.v0.beta.
|
||||
VersionBeta Version = "beta"
|
||||
)
|
||||
|
||||
// AllVersions is a list of all versions of the GCE API.
|
||||
var AllVersions = []Version{
|
||||
VersionGA,
|
||||
VersionAlpha,
|
||||
VersionBeta,
|
||||
}
|
||||
|
||||
// AllServices are a list of all the services to generate code for. Keep
|
||||
// this list in lexiographical order by object type.
|
||||
var AllServices = []*ServiceInfo{
|
||||
{
|
||||
Object: "Address",
|
||||
Service: "Addresses",
|
||||
Resource: "addresses",
|
||||
keyType: Regional,
|
||||
serviceType: reflect.TypeOf(&ga.AddressesService{}),
|
||||
},
|
||||
{
|
||||
Object: "Address",
|
||||
Service: "Addresses",
|
||||
Resource: "addresses",
|
||||
version: VersionAlpha,
|
||||
keyType: Regional,
|
||||
serviceType: reflect.TypeOf(&alpha.AddressesService{}),
|
||||
},
|
||||
{
|
||||
Object: "Address",
|
||||
Service: "Addresses",
|
||||
Resource: "addresses",
|
||||
version: VersionBeta,
|
||||
keyType: Regional,
|
||||
serviceType: reflect.TypeOf(&beta.AddressesService{}),
|
||||
},
|
||||
{
|
||||
Object: "Address",
|
||||
Service: "GlobalAddresses",
|
||||
Resource: "addresses",
|
||||
keyType: Global,
|
||||
serviceType: reflect.TypeOf(&ga.GlobalAddressesService{}),
|
||||
},
|
||||
{
|
||||
Object: "BackendService",
|
||||
Service: "BackendServices",
|
||||
Resource: "backendServices",
|
||||
keyType: Global,
|
||||
serviceType: reflect.TypeOf(&ga.BackendServicesService{}),
|
||||
additionalMethods: []string{
|
||||
"GetHealth",
|
||||
"Update",
|
||||
},
|
||||
},
|
||||
{
|
||||
Object: "BackendService",
|
||||
Service: "BackendServices",
|
||||
Resource: "backendServices",
|
||||
version: VersionAlpha,
|
||||
keyType: Global,
|
||||
serviceType: reflect.TypeOf(&alpha.BackendServicesService{}),
|
||||
additionalMethods: []string{"Update"},
|
||||
},
|
||||
{
|
||||
Object: "BackendService",
|
||||
Service: "RegionBackendServices",
|
||||
Resource: "backendServices",
|
||||
version: VersionGA,
|
||||
keyType: Regional,
|
||||
serviceType: reflect.TypeOf(&ga.RegionBackendServicesService{}),
|
||||
additionalMethods: []string{
|
||||
"GetHealth",
|
||||
"Update",
|
||||
},
|
||||
},
|
||||
{
|
||||
Object: "BackendService",
|
||||
Service: "RegionBackendServices",
|
||||
Resource: "backendServices",
|
||||
version: VersionAlpha,
|
||||
keyType: Regional,
|
||||
serviceType: reflect.TypeOf(&alpha.RegionBackendServicesService{}),
|
||||
additionalMethods: []string{
|
||||
"GetHealth",
|
||||
"Update",
|
||||
},
|
||||
},
|
||||
{
|
||||
Object: "Disk",
|
||||
Service: "Disks",
|
||||
Resource: "disks",
|
||||
keyType: Zonal,
|
||||
serviceType: reflect.TypeOf(&ga.DisksService{}),
|
||||
},
|
||||
{
|
||||
Object: "Disk",
|
||||
Service: "Disks",
|
||||
Resource: "disks",
|
||||
version: VersionAlpha,
|
||||
keyType: Zonal,
|
||||
serviceType: reflect.TypeOf(&alpha.DisksService{}),
|
||||
},
|
||||
{
|
||||
Object: "Disk",
|
||||
Service: "RegionDisks",
|
||||
Resource: "disks",
|
||||
version: VersionAlpha,
|
||||
keyType: Regional,
|
||||
serviceType: reflect.TypeOf(&alpha.DisksService{}),
|
||||
},
|
||||
{
|
||||
Object: "Firewall",
|
||||
Service: "Firewalls",
|
||||
Resource: "firewalls",
|
||||
keyType: Global,
|
||||
serviceType: reflect.TypeOf(&ga.FirewallsService{}),
|
||||
additionalMethods: []string{
|
||||
"Update",
|
||||
},
|
||||
},
|
||||
{
|
||||
Object: "ForwardingRule",
|
||||
Service: "ForwardingRules",
|
||||
Resource: "forwardingRules",
|
||||
keyType: Regional,
|
||||
serviceType: reflect.TypeOf(&ga.ForwardingRulesService{}),
|
||||
},
|
||||
{
|
||||
Object: "ForwardingRule",
|
||||
Service: "ForwardingRules",
|
||||
Resource: "forwardingRules",
|
||||
version: VersionAlpha,
|
||||
keyType: Regional,
|
||||
serviceType: reflect.TypeOf(&alpha.ForwardingRulesService{}),
|
||||
},
|
||||
{
|
||||
Object: "ForwardingRule",
|
||||
Service: "GlobalForwardingRules",
|
||||
Resource: "forwardingRules",
|
||||
keyType: Global,
|
||||
serviceType: reflect.TypeOf(&ga.GlobalForwardingRulesService{}),
|
||||
additionalMethods: []string{
|
||||
"SetTarget",
|
||||
},
|
||||
},
|
||||
{
|
||||
Object: "HealthCheck",
|
||||
Service: "HealthChecks",
|
||||
Resource: "healthChecks",
|
||||
keyType: Global,
|
||||
serviceType: reflect.TypeOf(&ga.HealthChecksService{}),
|
||||
additionalMethods: []string{
|
||||
"Update",
|
||||
},
|
||||
},
|
||||
{
|
||||
Object: "HealthCheck",
|
||||
Service: "HealthChecks",
|
||||
Resource: "healthChecks",
|
||||
version: VersionAlpha,
|
||||
keyType: Global,
|
||||
serviceType: reflect.TypeOf(&alpha.HealthChecksService{}),
|
||||
additionalMethods: []string{
|
||||
"Update",
|
||||
},
|
||||
},
|
||||
{
|
||||
Object: "HttpHealthCheck",
|
||||
Service: "HttpHealthChecks",
|
||||
Resource: "httpHealthChecks",
|
||||
keyType: Global,
|
||||
serviceType: reflect.TypeOf(&ga.HttpHealthChecksService{}),
|
||||
additionalMethods: []string{
|
||||
"Update",
|
||||
},
|
||||
},
|
||||
{
|
||||
Object: "HttpsHealthCheck",
|
||||
Service: "HttpsHealthChecks",
|
||||
Resource: "httpsHealthChecks",
|
||||
keyType: Global,
|
||||
serviceType: reflect.TypeOf(&ga.HttpsHealthChecksService{}),
|
||||
additionalMethods: []string{
|
||||
"Update",
|
||||
},
|
||||
},
|
||||
{
|
||||
Object: "InstanceGroup",
|
||||
Service: "InstanceGroups",
|
||||
Resource: "instanceGroups",
|
||||
keyType: Zonal,
|
||||
serviceType: reflect.TypeOf(&ga.InstanceGroupsService{}),
|
||||
additionalMethods: []string{
|
||||
"AddInstances",
|
||||
"ListInstances",
|
||||
"RemoveInstances",
|
||||
"SetNamedPorts",
|
||||
},
|
||||
},
|
||||
{
|
||||
Object: "Instance",
|
||||
Service: "Instances",
|
||||
Resource: "instances",
|
||||
keyType: Zonal,
|
||||
serviceType: reflect.TypeOf(&ga.InstancesService{}),
|
||||
additionalMethods: []string{
|
||||
"AttachDisk",
|
||||
"DetachDisk",
|
||||
},
|
||||
},
|
||||
{
|
||||
Object: "Instance",
|
||||
Service: "Instances",
|
||||
Resource: "instances",
|
||||
version: VersionBeta,
|
||||
keyType: Zonal,
|
||||
serviceType: reflect.TypeOf(&beta.InstancesService{}),
|
||||
additionalMethods: []string{
|
||||
"AttachDisk",
|
||||
"DetachDisk",
|
||||
"UpdateNetworkInterface",
|
||||
},
|
||||
},
|
||||
{
|
||||
Object: "Instance",
|
||||
Service: "Instances",
|
||||
Resource: "instances",
|
||||
version: VersionAlpha,
|
||||
keyType: Zonal,
|
||||
serviceType: reflect.TypeOf(&alpha.InstancesService{}),
|
||||
additionalMethods: []string{
|
||||
"AttachDisk",
|
||||
"DetachDisk",
|
||||
"UpdateNetworkInterface",
|
||||
},
|
||||
},
|
||||
{
|
||||
Object: "NetworkEndpointGroup",
|
||||
Service: "NetworkEndpointGroups",
|
||||
Resource: "networkEndpointGroups",
|
||||
version: VersionAlpha,
|
||||
keyType: Zonal,
|
||||
serviceType: reflect.TypeOf(&alpha.NetworkEndpointGroupsService{}),
|
||||
additionalMethods: []string{
|
||||
"AttachNetworkEndpoints",
|
||||
"DetachNetworkEndpoints",
|
||||
"ListNetworkEndpoints",
|
||||
},
|
||||
options: AggregatedList,
|
||||
},
|
||||
{
|
||||
Object: "Project",
|
||||
Service: "Projects",
|
||||
Resource: "projects",
|
||||
keyType: Global,
|
||||
// Generate only the stub with no methods.
|
||||
options: NoGet | NoList | NoInsert | NoDelete | CustomOps,
|
||||
serviceType: reflect.TypeOf(&ga.ProjectsService{}),
|
||||
},
|
||||
{
|
||||
Object: "Region",
|
||||
Service: "Regions",
|
||||
Resource: "regions",
|
||||
keyType: Global,
|
||||
options: ReadOnly,
|
||||
serviceType: reflect.TypeOf(&ga.RegionsService{}),
|
||||
},
|
||||
{
|
||||
Object: "Route",
|
||||
Service: "Routes",
|
||||
Resource: "routes",
|
||||
keyType: Global,
|
||||
serviceType: reflect.TypeOf(&ga.RoutesService{}),
|
||||
},
|
||||
{
|
||||
Object: "SslCertificate",
|
||||
Service: "SslCertificates",
|
||||
Resource: "sslCertificates",
|
||||
keyType: Global,
|
||||
serviceType: reflect.TypeOf(&ga.SslCertificatesService{}),
|
||||
},
|
||||
{
|
||||
Object: "TargetHttpProxy",
|
||||
Service: "TargetHttpProxies",
|
||||
Resource: "targetHttpProxies",
|
||||
keyType: Global,
|
||||
serviceType: reflect.TypeOf(&ga.TargetHttpProxiesService{}),
|
||||
additionalMethods: []string{
|
||||
"SetUrlMap",
|
||||
},
|
||||
},
|
||||
{
|
||||
Object: "TargetHttpsProxy",
|
||||
Service: "TargetHttpsProxies",
|
||||
Resource: "targetHttpsProxies",
|
||||
keyType: Global,
|
||||
serviceType: reflect.TypeOf(&ga.TargetHttpsProxiesService{}),
|
||||
additionalMethods: []string{
|
||||
"SetSslCertificates",
|
||||
"SetUrlMap",
|
||||
},
|
||||
},
|
||||
{
|
||||
Object: "TargetPool",
|
||||
Service: "TargetPools",
|
||||
Resource: "targetPools",
|
||||
keyType: Regional,
|
||||
serviceType: reflect.TypeOf(&ga.TargetPoolsService{}),
|
||||
additionalMethods: []string{
|
||||
"AddInstance",
|
||||
"RemoveInstance",
|
||||
},
|
||||
},
|
||||
{
|
||||
Object: "UrlMap",
|
||||
Service: "UrlMaps",
|
||||
Resource: "urlMaps",
|
||||
keyType: Global,
|
||||
serviceType: reflect.TypeOf(&ga.UrlMapsService{}),
|
||||
additionalMethods: []string{
|
||||
"Update",
|
||||
},
|
||||
},
|
||||
{
|
||||
Object: "Zone",
|
||||
Service: "Zones",
|
||||
Resource: "zones",
|
||||
keyType: Global,
|
||||
options: ReadOnly,
|
||||
serviceType: reflect.TypeOf(&ga.ZonesService{}),
|
||||
},
|
||||
}
|
337
vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud/meta/method.go
generated
vendored
Normal file
337
vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud/meta/method.go
generated
vendored
Normal file
@ -0,0 +1,337 @@
|
||||
/*
|
||||
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 meta
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func newArg(t reflect.Type) *arg {
|
||||
ret := &arg{}
|
||||
|
||||
// Dereference the pointer types to get at the underlying concrete type.
|
||||
Loop:
|
||||
for {
|
||||
switch t.Kind() {
|
||||
case reflect.Ptr:
|
||||
ret.numPtr++
|
||||
t = t.Elem()
|
||||
default:
|
||||
ret.pkg = t.PkgPath()
|
||||
ret.typeName += t.Name()
|
||||
break Loop
|
||||
}
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
type arg struct {
|
||||
pkg, typeName string
|
||||
numPtr int
|
||||
}
|
||||
|
||||
func (a *arg) normalizedPkg() string {
|
||||
if a.pkg == "" {
|
||||
return ""
|
||||
}
|
||||
|
||||
// Strip the repo.../vendor/ prefix from the package path if present.
|
||||
parts := strings.Split(a.pkg, "/")
|
||||
// Remove vendor prefix.
|
||||
for i := 0; i < len(parts); i++ {
|
||||
if parts[i] == "vendor" {
|
||||
parts = parts[i+1:]
|
||||
break
|
||||
}
|
||||
}
|
||||
switch strings.Join(parts, "/") {
|
||||
case "google.golang.org/api/compute/v1":
|
||||
return "ga."
|
||||
case "google.golang.org/api/compute/v0.alpha":
|
||||
return "alpha."
|
||||
case "google.golang.org/api/compute/v0.beta":
|
||||
return "beta."
|
||||
default:
|
||||
panic(fmt.Errorf("unhandled package %q", a.pkg))
|
||||
}
|
||||
}
|
||||
|
||||
func (a *arg) String() string {
|
||||
var ret string
|
||||
for i := 0; i < a.numPtr; i++ {
|
||||
ret += "*"
|
||||
}
|
||||
ret += a.normalizedPkg()
|
||||
ret += a.typeName
|
||||
return ret
|
||||
}
|
||||
|
||||
// newMethod returns a newly initialized method.
|
||||
func newMethod(s *ServiceInfo, m reflect.Method) *Method {
|
||||
ret := &Method{
|
||||
ServiceInfo: s,
|
||||
m: m,
|
||||
kind: MethodOperation,
|
||||
ReturnType: "",
|
||||
}
|
||||
ret.init()
|
||||
return ret
|
||||
}
|
||||
|
||||
// MethodKind is the type of method that we are generated code for.
|
||||
type MethodKind int
|
||||
|
||||
const (
|
||||
// MethodOperation is a long running method that returns an operation.
|
||||
MethodOperation MethodKind = iota
|
||||
// MethodGet is a method that immediately returns some data.
|
||||
MethodGet MethodKind = iota
|
||||
// MethodPaged is a method that returns a paged set of data.
|
||||
MethodPaged MethodKind = iota
|
||||
)
|
||||
|
||||
// Method is used to generate the calling code for non-standard methods.
|
||||
type Method struct {
|
||||
*ServiceInfo
|
||||
m reflect.Method
|
||||
|
||||
kind MethodKind
|
||||
// ReturnType is the return type for the method.
|
||||
ReturnType string
|
||||
// ItemType is the type of the individual elements returns from a
|
||||
// Pages() call. This is only applicable for MethodPaged kind.
|
||||
ItemType string
|
||||
}
|
||||
|
||||
// IsOperation is true if the method is an Operation.
|
||||
func (m *Method) IsOperation() bool {
|
||||
return m.kind == MethodOperation
|
||||
}
|
||||
|
||||
// IsPaged is true if the method paged.
|
||||
func (m *Method) IsPaged() bool {
|
||||
return m.kind == MethodPaged
|
||||
}
|
||||
|
||||
// IsGet is true if the method simple get.
|
||||
func (m *Method) IsGet() bool {
|
||||
return m.kind == MethodGet
|
||||
}
|
||||
|
||||
// argsSkip is the number of arguments to skip when generating the
|
||||
// synthesized method.
|
||||
func (m *Method) argsSkip() int {
|
||||
switch m.keyType {
|
||||
case Zonal:
|
||||
return 4
|
||||
case Regional:
|
||||
return 4
|
||||
case Global:
|
||||
return 3
|
||||
}
|
||||
panic(fmt.Errorf("invalid KeyType %v", m.keyType))
|
||||
}
|
||||
|
||||
// args return a list of arguments to the method, skipping the first skip
|
||||
// elements. If nameArgs is true, then the arguments will include a generated
|
||||
// parameter name (arg<N>). prefix will be added to the parameters.
|
||||
func (m *Method) args(skip int, nameArgs bool, prefix []string) []string {
|
||||
var args []*arg
|
||||
fType := m.m.Func.Type()
|
||||
for i := 0; i < fType.NumIn(); i++ {
|
||||
t := fType.In(i)
|
||||
args = append(args, newArg(t))
|
||||
}
|
||||
|
||||
var a []string
|
||||
for i := skip; i < fType.NumIn(); i++ {
|
||||
if nameArgs {
|
||||
a = append(a, fmt.Sprintf("arg%d %s", i-skip, args[i]))
|
||||
} else {
|
||||
a = append(a, args[i].String())
|
||||
}
|
||||
}
|
||||
return append(prefix, a...)
|
||||
}
|
||||
|
||||
// init the method. This performs some rudimentary static checking as well as
|
||||
// determines the kind of method by looking at the shape (method signature) of
|
||||
// the object.
|
||||
func (m *Method) init() {
|
||||
fType := m.m.Func.Type()
|
||||
if fType.NumIn() < m.argsSkip() {
|
||||
err := fmt.Errorf("method %q.%q, arity = %d which is less than required (< %d)",
|
||||
m.Service, m.Name(), fType.NumIn(), m.argsSkip())
|
||||
panic(err)
|
||||
}
|
||||
// Skipped args should all be string (they will be projectID, zone, region etc).
|
||||
for i := 1; i < m.argsSkip(); i++ {
|
||||
if fType.In(i).Kind() != reflect.String {
|
||||
panic(fmt.Errorf("method %q.%q: skipped args can only be strings", m.Service, m.Name()))
|
||||
}
|
||||
}
|
||||
// Return of the method must return a single value of type *xxxCall.
|
||||
if fType.NumOut() != 1 || fType.Out(0).Kind() != reflect.Ptr || !strings.HasSuffix(fType.Out(0).Elem().Name(), "Call") {
|
||||
panic(fmt.Errorf("method %q.%q: generator only supports methods returning an *xxxCall object",
|
||||
m.Service, m.Name()))
|
||||
}
|
||||
returnType := fType.Out(0)
|
||||
returnTypeName := fType.Out(0).Elem().Name()
|
||||
// xxxCall must have a Do() method.
|
||||
doMethod, ok := returnType.MethodByName("Do")
|
||||
if !ok {
|
||||
panic(fmt.Errorf("method %q.%q: return type %q does not have a Do() method",
|
||||
m.Service, m.Name(), returnTypeName))
|
||||
}
|
||||
_, hasPages := returnType.MethodByName("Pages")
|
||||
// Do() method must return (*T, error).
|
||||
switch doMethod.Func.Type().NumOut() {
|
||||
case 2:
|
||||
out0 := doMethod.Func.Type().Out(0)
|
||||
if out0.Kind() != reflect.Ptr {
|
||||
panic(fmt.Errorf("method %q.%q: return type %q of Do() = S, _; S must be pointer type (%v)",
|
||||
m.Service, m.Name(), returnTypeName, out0))
|
||||
}
|
||||
m.ReturnType = out0.Elem().Name()
|
||||
switch {
|
||||
case out0.Elem().Name() == "Operation":
|
||||
m.kind = MethodOperation
|
||||
case hasPages:
|
||||
m.kind = MethodPaged
|
||||
// Pages() returns a xxxList that has the actual list
|
||||
// of objects in the xxxList.Items field.
|
||||
listType := out0.Elem()
|
||||
itemsField, ok := listType.FieldByName("Items")
|
||||
if !ok {
|
||||
panic(fmt.Errorf("method %q.%q: paged return type %q does not have a .Items field", m.Service, m.Name(), listType.Name()))
|
||||
}
|
||||
// itemsField will be a []*ItemType. Dereference to
|
||||
// extract the ItemType.
|
||||
itemsType := itemsField.Type
|
||||
if itemsType.Kind() != reflect.Slice && itemsType.Elem().Kind() != reflect.Ptr {
|
||||
panic(fmt.Errorf("method %q.%q: paged return type %q.Items is not an array of pointers", m.Service, m.Name(), listType.Name()))
|
||||
}
|
||||
m.ItemType = itemsType.Elem().Elem().Name()
|
||||
default:
|
||||
m.kind = MethodGet
|
||||
}
|
||||
// Second argument must be "error".
|
||||
if doMethod.Func.Type().Out(1).Name() != "error" {
|
||||
panic(fmt.Errorf("method %q.%q: return type %q of Do() = S, T; T must be 'error'",
|
||||
m.Service, m.Name(), returnTypeName))
|
||||
}
|
||||
break
|
||||
default:
|
||||
panic(fmt.Errorf("method %q.%q: %q Do() return type is not handled by the generator",
|
||||
m.Service, m.Name(), returnTypeName))
|
||||
}
|
||||
}
|
||||
|
||||
// Name is the name of the method.
|
||||
func (m *Method) Name() string {
|
||||
return m.m.Name
|
||||
}
|
||||
|
||||
// CallArgs is a list of comma separated "argN" used for calling the method.
|
||||
// For example, if the method has two additional arguments, this will return
|
||||
// "arg0, arg1".
|
||||
func (m *Method) CallArgs() string {
|
||||
var args []string
|
||||
for i := m.argsSkip(); i < m.m.Func.Type().NumIn(); i++ {
|
||||
args = append(args, fmt.Sprintf("arg%d", i-m.argsSkip()))
|
||||
}
|
||||
if len(args) == 0 {
|
||||
return ""
|
||||
}
|
||||
return fmt.Sprintf(", %s", strings.Join(args, ", "))
|
||||
}
|
||||
|
||||
// MockHookName is the name of the hook function in the mock.
|
||||
func (m *Method) MockHookName() string {
|
||||
return m.m.Name + "Hook"
|
||||
}
|
||||
|
||||
// MockHook is the definition of the hook function.
|
||||
func (m *Method) MockHook() string {
|
||||
args := m.args(m.argsSkip(), false, []string{
|
||||
"context.Context",
|
||||
"*meta.Key",
|
||||
})
|
||||
if m.kind == MethodPaged {
|
||||
args = append(args, "*filter.F")
|
||||
}
|
||||
|
||||
args = append(args, fmt.Sprintf("*%s", m.MockWrapType()))
|
||||
|
||||
switch m.kind {
|
||||
case MethodOperation:
|
||||
return fmt.Sprintf("%v func(%v) error", m.MockHookName(), strings.Join(args, ", "))
|
||||
case MethodGet:
|
||||
return fmt.Sprintf("%v func(%v) (*%v.%v, error)", m.MockHookName(), strings.Join(args, ", "), m.Version(), m.ReturnType)
|
||||
case MethodPaged:
|
||||
return fmt.Sprintf("%v func(%v) ([]*%v.%v, error)", m.MockHookName(), strings.Join(args, ", "), m.Version(), m.ItemType)
|
||||
default:
|
||||
panic(fmt.Errorf("invalid method kind: %v", m.kind))
|
||||
}
|
||||
}
|
||||
|
||||
// FcnArgs is the function signature for the definition of the method.
|
||||
func (m *Method) FcnArgs() string {
|
||||
args := m.args(m.argsSkip(), true, []string{
|
||||
"ctx context.Context",
|
||||
"key *meta.Key",
|
||||
})
|
||||
if m.kind == MethodPaged {
|
||||
args = append(args, "fl *filter.F")
|
||||
}
|
||||
|
||||
switch m.kind {
|
||||
case MethodOperation:
|
||||
return fmt.Sprintf("%v(%v) error", m.m.Name, strings.Join(args, ", "))
|
||||
case MethodGet:
|
||||
return fmt.Sprintf("%v(%v) (*%v.%v, error)", m.m.Name, strings.Join(args, ", "), m.Version(), m.ReturnType)
|
||||
case MethodPaged:
|
||||
return fmt.Sprintf("%v(%v) ([]*%v.%v, error)", m.m.Name, strings.Join(args, ", "), m.Version(), m.ItemType)
|
||||
default:
|
||||
panic(fmt.Errorf("invalid method kind: %v", m.kind))
|
||||
}
|
||||
}
|
||||
|
||||
// InterfaceFunc is the function declaration of the method in the interface.
|
||||
func (m *Method) InterfaceFunc() string {
|
||||
args := []string{
|
||||
"context.Context",
|
||||
"*meta.Key",
|
||||
}
|
||||
args = m.args(m.argsSkip(), false, args)
|
||||
if m.kind == MethodPaged {
|
||||
args = append(args, "*filter.F")
|
||||
}
|
||||
|
||||
switch m.kind {
|
||||
case MethodOperation:
|
||||
return fmt.Sprintf("%v(%v) error", m.m.Name, strings.Join(args, ", "))
|
||||
case MethodGet:
|
||||
return fmt.Sprintf("%v(%v) (*%v.%v, error)", m.m.Name, strings.Join(args, ", "), m.Version(), m.ReturnType)
|
||||
case MethodPaged:
|
||||
return fmt.Sprintf("%v(%v) ([]*%v.%v, error)", m.m.Name, strings.Join(args, ", "), m.Version(), m.ItemType)
|
||||
default:
|
||||
panic(fmt.Errorf("invalid method kind: %v", m.kind))
|
||||
}
|
||||
}
|
277
vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud/meta/service.go
generated
vendored
Normal file
277
vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud/meta/service.go
generated
vendored
Normal file
@ -0,0 +1,277 @@
|
||||
/*
|
||||
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 meta
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"reflect"
|
||||
)
|
||||
|
||||
// ServiceInfo defines the entry for a Service that code will be generated for.
|
||||
type ServiceInfo struct {
|
||||
// Object is the Go name of the object type that the service deals
|
||||
// with. Example: "ForwardingRule".
|
||||
Object string
|
||||
// Service is the Go name of the service struct i.e. where the methods
|
||||
// are defined. Examples: "GlobalForwardingRules".
|
||||
Service string
|
||||
// Resource is the plural noun of the resource in the compute API URL (e.g.
|
||||
// "forwardingRules").
|
||||
Resource string
|
||||
// version if unspecified will be assumed to be VersionGA.
|
||||
version Version
|
||||
keyType KeyType
|
||||
serviceType reflect.Type
|
||||
|
||||
additionalMethods []string
|
||||
options int
|
||||
aggregatedListField string
|
||||
}
|
||||
|
||||
// Version returns the version of the Service, defaulting to GA if APIVersion
|
||||
// is empty.
|
||||
func (i *ServiceInfo) Version() Version {
|
||||
if i.version == "" {
|
||||
return VersionGA
|
||||
}
|
||||
return i.version
|
||||
}
|
||||
|
||||
// VersionTitle returns the capitalized golang CamelCase name for the version.
|
||||
func (i *ServiceInfo) VersionTitle() string {
|
||||
switch i.Version() {
|
||||
case VersionGA:
|
||||
return "GA"
|
||||
case VersionAlpha:
|
||||
return "Alpha"
|
||||
case VersionBeta:
|
||||
return "Beta"
|
||||
}
|
||||
panic(fmt.Errorf("invalid version %q", i.Version()))
|
||||
}
|
||||
|
||||
// WrapType is the name of the wrapper service type.
|
||||
func (i *ServiceInfo) WrapType() string {
|
||||
switch i.Version() {
|
||||
case VersionGA:
|
||||
return i.Service
|
||||
case VersionAlpha:
|
||||
return "Alpha" + i.Service
|
||||
case VersionBeta:
|
||||
return "Beta" + i.Service
|
||||
}
|
||||
return "Invalid"
|
||||
}
|
||||
|
||||
// WrapTypeOps is the name of the additional operations type.
|
||||
func (i *ServiceInfo) WrapTypeOps() string {
|
||||
return i.WrapType() + "Ops"
|
||||
}
|
||||
|
||||
// FQObjectType is fully qualified name of the object (e.g. compute.Instance).
|
||||
func (i *ServiceInfo) FQObjectType() string {
|
||||
return fmt.Sprintf("%v.%v", i.Version(), i.Object)
|
||||
}
|
||||
|
||||
// ObjectListType is the compute List type for the object (contains Items field).
|
||||
func (i *ServiceInfo) ObjectListType() string {
|
||||
return fmt.Sprintf("%v.%vList", i.Version(), i.Object)
|
||||
}
|
||||
|
||||
// ObjectAggregatedListType is the compute List type for the object (contains Items field).
|
||||
func (i *ServiceInfo) ObjectAggregatedListType() string {
|
||||
return fmt.Sprintf("%v.%vAggregatedList", i.Version(), i.Object)
|
||||
}
|
||||
|
||||
// MockWrapType is the name of the concrete mock for this type.
|
||||
func (i *ServiceInfo) MockWrapType() string {
|
||||
return "Mock" + i.WrapType()
|
||||
}
|
||||
|
||||
// MockField is the name of the field in the mock struct.
|
||||
func (i *ServiceInfo) MockField() string {
|
||||
return "Mock" + i.WrapType()
|
||||
}
|
||||
|
||||
// GCEWrapType is the name of the GCE wrapper type.
|
||||
func (i *ServiceInfo) GCEWrapType() string {
|
||||
return "GCE" + i.WrapType()
|
||||
}
|
||||
|
||||
// Field is the name of the GCE struct.
|
||||
func (i *ServiceInfo) Field() string {
|
||||
return "gce" + i.WrapType()
|
||||
}
|
||||
|
||||
// Methods returns a list of additional methods to generate code for.
|
||||
func (i *ServiceInfo) Methods() []*Method {
|
||||
methods := map[string]bool{}
|
||||
for _, m := range i.additionalMethods {
|
||||
methods[m] = true
|
||||
}
|
||||
|
||||
var ret []*Method
|
||||
for j := 0; j < i.serviceType.NumMethod(); j++ {
|
||||
m := i.serviceType.Method(j)
|
||||
if _, ok := methods[m.Name]; !ok {
|
||||
continue
|
||||
}
|
||||
ret = append(ret, newMethod(i, m))
|
||||
methods[m.Name] = false
|
||||
}
|
||||
|
||||
for k, b := range methods {
|
||||
if b {
|
||||
panic(fmt.Errorf("method %q was not found in service %q", k, i.Service))
|
||||
}
|
||||
}
|
||||
|
||||
return ret
|
||||
}
|
||||
|
||||
// KeyIsGlobal is true if the key is global.
|
||||
func (i *ServiceInfo) KeyIsGlobal() bool {
|
||||
return i.keyType == Global
|
||||
}
|
||||
|
||||
// KeyIsRegional is true if the key is regional.
|
||||
func (i *ServiceInfo) KeyIsRegional() bool {
|
||||
return i.keyType == Regional
|
||||
}
|
||||
|
||||
// KeyIsZonal is true if the key is zonal.
|
||||
func (i *ServiceInfo) KeyIsZonal() bool {
|
||||
return i.keyType == Zonal
|
||||
}
|
||||
|
||||
// MakeKey returns the call used to create the appropriate key type.
|
||||
func (i *ServiceInfo) MakeKey(name, location string) string {
|
||||
switch i.keyType {
|
||||
case Global:
|
||||
return fmt.Sprintf("GlobalKey(%q)", name)
|
||||
case Regional:
|
||||
return fmt.Sprintf("RegionalKey(%q, %q)", name, location)
|
||||
case Zonal:
|
||||
return fmt.Sprintf("ZonalKey(%q, %q)", name, location)
|
||||
}
|
||||
return "Invalid"
|
||||
}
|
||||
|
||||
// GenerateGet is true if the method is to be generated.
|
||||
func (i *ServiceInfo) GenerateGet() bool {
|
||||
return i.options&NoGet == 0
|
||||
}
|
||||
|
||||
// GenerateList is true if the method is to be generated.
|
||||
func (i *ServiceInfo) GenerateList() bool {
|
||||
return i.options&NoList == 0
|
||||
}
|
||||
|
||||
// GenerateDelete is true if the method is to be generated.
|
||||
func (i *ServiceInfo) GenerateDelete() bool {
|
||||
return i.options&NoDelete == 0
|
||||
}
|
||||
|
||||
// GenerateInsert is true if the method is to be generated.
|
||||
func (i *ServiceInfo) GenerateInsert() bool {
|
||||
return i.options&NoInsert == 0
|
||||
}
|
||||
|
||||
// GenerateCustomOps is true if we should generated a xxxOps interface for
|
||||
// adding additional methods to the generated interface.
|
||||
func (i *ServiceInfo) GenerateCustomOps() bool {
|
||||
return i.options&CustomOps != 0
|
||||
}
|
||||
|
||||
// AggregatedList is true if the method is to be generated.
|
||||
func (i *ServiceInfo) AggregatedList() bool {
|
||||
return i.options&AggregatedList != 0
|
||||
}
|
||||
|
||||
// AggregatedListField is the name of the field used for the aggregated list
|
||||
// call. This is typically the same as the name of the service, but can be
|
||||
// customized by setting the aggregatedListField field.
|
||||
func (i *ServiceInfo) AggregatedListField() string {
|
||||
if i.aggregatedListField == "" {
|
||||
return i.Service
|
||||
}
|
||||
return i.aggregatedListField
|
||||
}
|
||||
|
||||
// ServiceGroup is a grouping of the same service but at different API versions.
|
||||
type ServiceGroup struct {
|
||||
Alpha *ServiceInfo
|
||||
Beta *ServiceInfo
|
||||
GA *ServiceInfo
|
||||
}
|
||||
|
||||
// Service returns any ServiceInfo object belonging to the ServiceGroup.
|
||||
func (sg *ServiceGroup) Service() string {
|
||||
switch {
|
||||
case sg.GA != nil:
|
||||
return sg.GA.Service
|
||||
case sg.Alpha != nil:
|
||||
return sg.Alpha.Service
|
||||
case sg.Beta != nil:
|
||||
return sg.Beta.Service
|
||||
default:
|
||||
panic(errors.New("service group is empty"))
|
||||
}
|
||||
}
|
||||
|
||||
// HasGA returns true if this object has a GA representation.
|
||||
func (sg *ServiceGroup) HasGA() bool {
|
||||
return sg.GA != nil
|
||||
}
|
||||
|
||||
// HasAlpha returns true if this object has a Alpha representation.
|
||||
func (sg *ServiceGroup) HasAlpha() bool {
|
||||
return sg.Alpha != nil
|
||||
}
|
||||
|
||||
// HasBeta returns true if this object has a Beta representation.
|
||||
func (sg *ServiceGroup) HasBeta() bool {
|
||||
return sg.Beta != nil
|
||||
}
|
||||
|
||||
// groupServices together by version.
|
||||
func groupServices(services []*ServiceInfo) map[string]*ServiceGroup {
|
||||
ret := map[string]*ServiceGroup{}
|
||||
for _, si := range services {
|
||||
if _, ok := ret[si.Service]; !ok {
|
||||
ret[si.Service] = &ServiceGroup{}
|
||||
}
|
||||
group := ret[si.Service]
|
||||
switch si.Version() {
|
||||
case VersionAlpha:
|
||||
group.Alpha = si
|
||||
case VersionBeta:
|
||||
group.Beta = si
|
||||
case VersionGA:
|
||||
group.GA = si
|
||||
}
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
// AllServicesByGroup is a map of service name to ServicesGroup.
|
||||
var AllServicesByGroup map[string]*ServiceGroup
|
||||
|
||||
func init() {
|
||||
AllServicesByGroup = groupServices(AllServices)
|
||||
}
|
30
vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud/mock/BUILD
generated
vendored
Normal file
30
vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud/mock/BUILD
generated
vendored
Normal file
@ -0,0 +1,30 @@
|
||||
load("@io_bazel_rules_go//go:def.bzl", "go_library")
|
||||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = ["mock.go"],
|
||||
importpath = "k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud/mock",
|
||||
visibility = ["//visibility:public"],
|
||||
deps = [
|
||||
"//pkg/cloudprovider/providers/gce/cloud:go_default_library",
|
||||
"//pkg/cloudprovider/providers/gce/cloud/meta:go_default_library",
|
||||
"//vendor/google.golang.org/api/compute/v0.alpha:go_default_library",
|
||||
"//vendor/google.golang.org/api/compute/v0.beta:go_default_library",
|
||||
"//vendor/google.golang.org/api/compute/v1:go_default_library",
|
||||
"//vendor/google.golang.org/api/googleapi:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "package-srcs",
|
||||
srcs = glob(["**"]),
|
||||
tags = ["automanaged"],
|
||||
visibility = ["//visibility:private"],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "all-srcs",
|
||||
srcs = [":package-srcs"],
|
||||
tags = ["automanaged"],
|
||||
visibility = ["//visibility:public"],
|
||||
)
|
228
vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud/mock/mock.go
generated
vendored
Normal file
228
vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud/mock/mock.go
generated
vendored
Normal file
@ -0,0 +1,228 @@
|
||||
/*
|
||||
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 mock encapsulates mocks for testing GCE provider functionality.
|
||||
// These methods are used to override the mock objects' methods in order to
|
||||
// intercept the standard processing and to add custom logic for test purposes.
|
||||
//
|
||||
// // Example usage:
|
||||
// cloud := cloud.NewMockGCE()
|
||||
// cloud.MockTargetPools.AddInstanceHook = mock.AddInstanceHook
|
||||
package mock
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/http"
|
||||
|
||||
alpha "google.golang.org/api/compute/v0.alpha"
|
||||
beta "google.golang.org/api/compute/v0.beta"
|
||||
ga "google.golang.org/api/compute/v1"
|
||||
"google.golang.org/api/googleapi"
|
||||
"k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud"
|
||||
"k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud/meta"
|
||||
)
|
||||
|
||||
// gceObject is an abstraction of all GCE API object in go client
|
||||
type gceObject interface {
|
||||
MarshalJSON() ([]byte, error)
|
||||
}
|
||||
|
||||
// AddInstanceHook mocks adding a Instance to MockTargetPools
|
||||
func AddInstanceHook(ctx context.Context, key *meta.Key, req *ga.TargetPoolsAddInstanceRequest, m *cloud.MockTargetPools) error {
|
||||
pool, err := m.Get(ctx, key)
|
||||
if err != nil {
|
||||
return &googleapi.Error{
|
||||
Code: http.StatusNotFound,
|
||||
Message: fmt.Sprintf("Key: %s was not found in TargetPools", key.String()),
|
||||
}
|
||||
}
|
||||
|
||||
for _, instance := range req.Instances {
|
||||
pool.Instances = append(pool.Instances, instance.Instance)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// RemoveInstanceHook mocks removing a Instance from MockTargetPools
|
||||
func RemoveInstanceHook(ctx context.Context, key *meta.Key, req *ga.TargetPoolsRemoveInstanceRequest, m *cloud.MockTargetPools) error {
|
||||
pool, err := m.Get(ctx, key)
|
||||
if err != nil {
|
||||
return &googleapi.Error{
|
||||
Code: http.StatusNotFound,
|
||||
Message: fmt.Sprintf("Key: %s was not found in TargetPools", key.String()),
|
||||
}
|
||||
}
|
||||
|
||||
for _, instanceToRemove := range req.Instances {
|
||||
for i, instance := range pool.Instances {
|
||||
if instanceToRemove.Instance == instance {
|
||||
// Delete instance from pool.Instances without preserving order
|
||||
pool.Instances[i] = pool.Instances[len(pool.Instances)-1]
|
||||
pool.Instances = pool.Instances[:len(pool.Instances)-1]
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func convertAndInsertAlphaForwardingRule(key *meta.Key, obj gceObject, mRules map[meta.Key]*cloud.MockForwardingRulesObj, version meta.Version, projectID string) (bool, error) {
|
||||
if !key.Valid() {
|
||||
return false, fmt.Errorf("invalid GCE key (%+v)", key)
|
||||
}
|
||||
|
||||
if _, ok := mRules[*key]; ok {
|
||||
err := &googleapi.Error{
|
||||
Code: http.StatusConflict,
|
||||
Message: fmt.Sprintf("MockForwardingRule %v exists", key),
|
||||
}
|
||||
return false, err
|
||||
}
|
||||
|
||||
enc, err := obj.MarshalJSON()
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
var fwdRule alpha.ForwardingRule
|
||||
if err := json.Unmarshal(enc, &fwdRule); err != nil {
|
||||
return false, err
|
||||
}
|
||||
// Set the default values for the Alpha fields.
|
||||
if fwdRule.NetworkTier == "" {
|
||||
fwdRule.NetworkTier = cloud.NetworkTierDefault.ToGCEValue()
|
||||
}
|
||||
|
||||
fwdRule.Name = key.Name
|
||||
if fwdRule.SelfLink == "" {
|
||||
fwdRule.SelfLink = cloud.SelfLink(version, projectID, "forwardingRules", key)
|
||||
}
|
||||
|
||||
mRules[*key] = &cloud.MockForwardingRulesObj{Obj: fwdRule}
|
||||
return true, nil
|
||||
}
|
||||
|
||||
// InsertFwdRuleHook mocks inserting a ForwardingRule. ForwardingRules are
|
||||
// expected to default to Premium tier if no NetworkTier is specified.
|
||||
func InsertFwdRuleHook(ctx context.Context, key *meta.Key, obj *ga.ForwardingRule, m *cloud.MockForwardingRules) (bool, error) {
|
||||
projectID := m.ProjectRouter.ProjectID(ctx, meta.VersionGA, "forwardingRules")
|
||||
return convertAndInsertAlphaForwardingRule(key, obj, m.Objects, meta.VersionGA, projectID)
|
||||
}
|
||||
|
||||
// InsertBetaFwdRuleHook mocks inserting a BetaForwardingRule.
|
||||
func InsertBetaFwdRuleHook(ctx context.Context, key *meta.Key, obj *beta.ForwardingRule, m *cloud.MockForwardingRules) (bool, error) {
|
||||
projectID := m.ProjectRouter.ProjectID(ctx, meta.VersionBeta, "forwardingRules")
|
||||
return convertAndInsertAlphaForwardingRule(key, obj, m.Objects, meta.VersionBeta, projectID)
|
||||
}
|
||||
|
||||
// InsertAlphaFwdRuleHook mocks inserting an AlphaForwardingRule.
|
||||
func InsertAlphaFwdRuleHook(ctx context.Context, key *meta.Key, obj *alpha.ForwardingRule, m *cloud.MockForwardingRules) (bool, error) {
|
||||
projectID := m.ProjectRouter.ProjectID(ctx, meta.VersionAlpha, "forwardingRules")
|
||||
return convertAndInsertAlphaForwardingRule(key, obj, m.Objects, meta.VersionAlpha, projectID)
|
||||
}
|
||||
|
||||
// Used to assign Addresses with no IP a unique IP address
|
||||
var ipCounter = 1
|
||||
|
||||
func convertAndInsertAlphaAddress(key *meta.Key, obj gceObject, mAddrs map[meta.Key]*cloud.MockAddressesObj, version meta.Version, projectID string) (bool, error) {
|
||||
if !key.Valid() {
|
||||
return false, fmt.Errorf("invalid GCE key (%+v)", key)
|
||||
}
|
||||
|
||||
if _, ok := mAddrs[*key]; ok {
|
||||
err := &googleapi.Error{
|
||||
Code: http.StatusConflict,
|
||||
Message: fmt.Sprintf("MockAddresses %v exists", key),
|
||||
}
|
||||
return false, err
|
||||
}
|
||||
|
||||
enc, err := obj.MarshalJSON()
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
var addr alpha.Address
|
||||
if err := json.Unmarshal(enc, &addr); err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
// Set default address type if not present.
|
||||
if addr.AddressType == "" {
|
||||
addr.AddressType = string(cloud.SchemeExternal)
|
||||
}
|
||||
|
||||
var existingAddresses []*ga.Address
|
||||
for _, obj := range mAddrs {
|
||||
existingAddresses = append(existingAddresses, obj.ToGA())
|
||||
}
|
||||
|
||||
for _, existingAddr := range existingAddresses {
|
||||
if addr.Address == existingAddr.Address {
|
||||
msg := fmt.Sprintf("MockAddresses IP %v in use", addr.Address)
|
||||
|
||||
// When the IP is already in use, this call returns a StatusBadRequest
|
||||
// if the address is an external address, and StatusConflict if an
|
||||
// internal address. This is to be consistent with actual GCE API.
|
||||
errorCode := http.StatusConflict
|
||||
if addr.AddressType == string(cloud.SchemeExternal) {
|
||||
errorCode = http.StatusBadRequest
|
||||
}
|
||||
|
||||
return false, &googleapi.Error{Code: errorCode, Message: msg}
|
||||
}
|
||||
}
|
||||
|
||||
// Set default values used in tests
|
||||
addr.Name = key.Name
|
||||
if addr.SelfLink == "" {
|
||||
addr.SelfLink = cloud.SelfLink(version, projectID, "addresses", key)
|
||||
}
|
||||
|
||||
if addr.Address == "" {
|
||||
addr.Address = fmt.Sprintf("1.2.3.%d", ipCounter)
|
||||
ipCounter++
|
||||
}
|
||||
|
||||
// Set the default values for the Alpha fields.
|
||||
if addr.NetworkTier == "" {
|
||||
addr.NetworkTier = cloud.NetworkTierDefault.ToGCEValue()
|
||||
}
|
||||
|
||||
mAddrs[*key] = &cloud.MockAddressesObj{Obj: addr}
|
||||
return true, nil
|
||||
}
|
||||
|
||||
// InsertAddressHook mocks inserting an Address.
|
||||
func InsertAddressHook(ctx context.Context, key *meta.Key, obj *ga.Address, m *cloud.MockAddresses) (bool, error) {
|
||||
projectID := m.ProjectRouter.ProjectID(ctx, meta.VersionGA, "addresses")
|
||||
return convertAndInsertAlphaAddress(key, obj, m.Objects, meta.VersionGA, projectID)
|
||||
}
|
||||
|
||||
// InsertBetaAddressHook mocks inserting a BetaAddress.
|
||||
func InsertBetaAddressHook(ctx context.Context, key *meta.Key, obj *beta.Address, m *cloud.MockAddresses) (bool, error) {
|
||||
projectID := m.ProjectRouter.ProjectID(ctx, meta.VersionBeta, "addresses")
|
||||
return convertAndInsertAlphaAddress(key, obj, m.Objects, meta.VersionBeta, projectID)
|
||||
}
|
||||
|
||||
// InsertAlphaAddressHook mocks inserting an Address. Addresses are expected to
|
||||
// default to Premium tier if no NetworkTier is specified.
|
||||
func InsertAlphaAddressHook(ctx context.Context, key *meta.Key, obj *alpha.Address, m *cloud.MockAlphaAddresses) (bool, error) {
|
||||
projectID := m.ProjectRouter.ProjectID(ctx, meta.VersionBeta, "addresses")
|
||||
return convertAndInsertAlphaAddress(key, obj, m.Objects, meta.VersionAlpha, projectID)
|
||||
}
|
151
vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud/mock_test.go
generated
vendored
Normal file
151
vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud/mock_test.go
generated
vendored
Normal file
@ -0,0 +1,151 @@
|
||||
/*
|
||||
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 cloud
|
||||
|
||||
import (
|
||||
"context"
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
alpha "google.golang.org/api/compute/v0.alpha"
|
||||
beta "google.golang.org/api/compute/v0.beta"
|
||||
ga "google.golang.org/api/compute/v1"
|
||||
|
||||
"k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud/filter"
|
||||
"k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud/meta"
|
||||
)
|
||||
|
||||
func TestMocks(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
// This test uses Addresses, but the logic that is generated is the same for
|
||||
// other basic objects.
|
||||
const region = "us-central1"
|
||||
|
||||
ctx := context.Background()
|
||||
pr := &SingleProjectRouter{"mock-project"}
|
||||
mock := NewMockGCE(pr)
|
||||
|
||||
keyAlpha := meta.RegionalKey("key-alpha", region)
|
||||
keyBeta := meta.RegionalKey("key-beta", region)
|
||||
keyGA := meta.RegionalKey("key-ga", region)
|
||||
key := keyAlpha
|
||||
|
||||
// Get not found.
|
||||
if _, err := mock.AlphaAddresses().Get(ctx, key); err == nil {
|
||||
t.Errorf("AlphaAddresses().Get(%v, %v) = _, nil; want error", ctx, key)
|
||||
}
|
||||
if _, err := mock.BetaAddresses().Get(ctx, key); err == nil {
|
||||
t.Errorf("BetaAddresses().Get(%v, %v) = _, nil; want error", ctx, key)
|
||||
}
|
||||
if _, err := mock.Addresses().Get(ctx, key); err == nil {
|
||||
t.Errorf("Addresses().Get(%v, %v) = _, nil; want error", ctx, key)
|
||||
}
|
||||
// Insert.
|
||||
{
|
||||
obj := &alpha.Address{}
|
||||
if err := mock.AlphaAddresses().Insert(ctx, keyAlpha, obj); err != nil {
|
||||
t.Errorf("AlphaAddresses().Insert(%v, %v, %v) = %v; want nil", ctx, key, obj, err)
|
||||
}
|
||||
}
|
||||
{
|
||||
obj := &beta.Address{}
|
||||
if err := mock.BetaAddresses().Insert(ctx, keyBeta, obj); err != nil {
|
||||
t.Errorf("BetaAddresses().Insert(%v, %v, %v) = %v; want nil", ctx, key, obj, err)
|
||||
}
|
||||
}
|
||||
{
|
||||
obj := &ga.Address{}
|
||||
if err := mock.Addresses().Insert(ctx, keyGA, &ga.Address{Name: "ga"}); err != nil {
|
||||
t.Errorf("Addresses().Insert(%v, %v, %v) = %v; want nil", ctx, key, obj, err)
|
||||
}
|
||||
}
|
||||
// Get across versions.
|
||||
if obj, err := mock.AlphaAddresses().Get(ctx, key); err != nil {
|
||||
t.Errorf("AlphaAddresses().Get(%v, %v) = %v, %v; want nil", ctx, key, obj, err)
|
||||
}
|
||||
if obj, err := mock.BetaAddresses().Get(ctx, key); err != nil {
|
||||
t.Errorf("BetaAddresses().Get(%v, %v) = %v, %v; want nil", ctx, key, obj, err)
|
||||
}
|
||||
if obj, err := mock.Addresses().Get(ctx, key); err != nil {
|
||||
t.Errorf("Addresses().Get(%v, %v) = %v, %v; want nil", ctx, key, obj, err)
|
||||
}
|
||||
// List across versions.
|
||||
want := map[string]bool{"key-alpha": true, "key-beta": true, "key-ga": true}
|
||||
{
|
||||
objs, err := mock.AlphaAddresses().List(ctx, region, filter.None)
|
||||
if err != nil {
|
||||
t.Errorf("AlphaAddresses().List(%v, %v, %v) = %v, %v; want _, nil", ctx, region, filter.None, objs, err)
|
||||
} else {
|
||||
got := map[string]bool{}
|
||||
for _, obj := range objs {
|
||||
got[obj.Name] = true
|
||||
}
|
||||
if !reflect.DeepEqual(got, want) {
|
||||
t.Errorf("AlphaAddresses().List(); got %+v, want %+v", got, want)
|
||||
}
|
||||
}
|
||||
}
|
||||
{
|
||||
objs, err := mock.BetaAddresses().List(ctx, region, filter.None)
|
||||
if err != nil {
|
||||
t.Errorf("BetaAddresses().List(%v, %v, %v) = %v, %v; want _, nil", ctx, region, filter.None, objs, err)
|
||||
} else {
|
||||
got := map[string]bool{}
|
||||
for _, obj := range objs {
|
||||
got[obj.Name] = true
|
||||
}
|
||||
if !reflect.DeepEqual(got, want) {
|
||||
t.Errorf("AlphaAddresses().List(); got %+v, want %+v", got, want)
|
||||
}
|
||||
}
|
||||
}
|
||||
{
|
||||
objs, err := mock.Addresses().List(ctx, region, filter.None)
|
||||
if err != nil {
|
||||
t.Errorf("Addresses().List(%v, %v, %v) = %v, %v; want _, nil", ctx, region, filter.None, objs, err)
|
||||
} else {
|
||||
got := map[string]bool{}
|
||||
for _, obj := range objs {
|
||||
got[obj.Name] = true
|
||||
}
|
||||
if !reflect.DeepEqual(got, want) {
|
||||
t.Errorf("AlphaAddresses().List(); got %+v, want %+v", got, want)
|
||||
}
|
||||
}
|
||||
}
|
||||
// Delete across versions.
|
||||
if err := mock.AlphaAddresses().Delete(ctx, keyAlpha); err != nil {
|
||||
t.Errorf("AlphaAddresses().Delete(%v, %v) = %v; want nil", ctx, key, err)
|
||||
}
|
||||
if err := mock.BetaAddresses().Delete(ctx, keyBeta); err != nil {
|
||||
t.Errorf("BetaAddresses().Delete(%v, %v) = %v; want nil", ctx, key, err)
|
||||
}
|
||||
if err := mock.Addresses().Delete(ctx, keyGA); err != nil {
|
||||
t.Errorf("Addresses().Delete(%v, %v) = %v; want nil", ctx, key, err)
|
||||
}
|
||||
// Delete not found.
|
||||
if err := mock.AlphaAddresses().Delete(ctx, keyAlpha); err == nil {
|
||||
t.Errorf("AlphaAddresses().Delete(%v, %v) = nil; want error", ctx, key)
|
||||
}
|
||||
if err := mock.BetaAddresses().Delete(ctx, keyBeta); err == nil {
|
||||
t.Errorf("BetaAddresses().Delete(%v, %v) = nil; want error", ctx, key)
|
||||
}
|
||||
if err := mock.Addresses().Delete(ctx, keyGA); err == nil {
|
||||
t.Errorf("Addresses().Delete(%v, %v) = nil; want error", ctx, key)
|
||||
}
|
||||
}
|
172
vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud/op.go
generated
vendored
Normal file
172
vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud/op.go
generated
vendored
Normal file
@ -0,0 +1,172 @@
|
||||
/*
|
||||
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 cloud
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/golang/glog"
|
||||
|
||||
alpha "google.golang.org/api/compute/v0.alpha"
|
||||
beta "google.golang.org/api/compute/v0.beta"
|
||||
ga "google.golang.org/api/compute/v1"
|
||||
|
||||
"k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud/meta"
|
||||
)
|
||||
|
||||
// operation is a GCE operation that can be watied on.
|
||||
type operation interface {
|
||||
// isDone queries GCE for the done status. This call can block.
|
||||
isDone(ctx context.Context) (bool, error)
|
||||
// rateLimitKey returns the rate limit key to use for the given operation.
|
||||
// This rate limit will govern how fast the server will be polled for
|
||||
// operation completion status.
|
||||
rateLimitKey() *RateLimitKey
|
||||
}
|
||||
|
||||
type gaOperation struct {
|
||||
s *Service
|
||||
projectID string
|
||||
key *meta.Key
|
||||
}
|
||||
|
||||
func (o *gaOperation) String() string {
|
||||
return fmt.Sprintf("gaOperation{%q, %v}", o.projectID, o.key)
|
||||
}
|
||||
|
||||
func (o *gaOperation) isDone(ctx context.Context) (bool, error) {
|
||||
var (
|
||||
op *ga.Operation
|
||||
err error
|
||||
)
|
||||
|
||||
switch o.key.Type() {
|
||||
case meta.Regional:
|
||||
op, err = o.s.GA.RegionOperations.Get(o.projectID, o.key.Region, o.key.Name).Context(ctx).Do()
|
||||
glog.V(5).Infof("GA.RegionOperations.Get(%v, %v, %v) = %+v, %v; ctx = %v", o.projectID, o.key.Region, o.key.Name, op, err, ctx)
|
||||
case meta.Zonal:
|
||||
op, err = o.s.GA.ZoneOperations.Get(o.projectID, o.key.Zone, o.key.Name).Context(ctx).Do()
|
||||
glog.V(5).Infof("GA.ZoneOperations.Get(%v, %v, %v) = %+v, %v; ctx = %v", o.projectID, o.key.Zone, o.key.Name, op, err, ctx)
|
||||
case meta.Global:
|
||||
op, err = o.s.GA.GlobalOperations.Get(o.projectID, o.key.Name).Context(ctx).Do()
|
||||
glog.V(5).Infof("GA.GlobalOperations.Get(%v, %v) = %+v, %v; ctx = %v", o.projectID, o.key.Name, op, err, ctx)
|
||||
default:
|
||||
return false, fmt.Errorf("invalid key type: %#v", o.key)
|
||||
}
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
return op != nil && op.Status == "DONE", nil
|
||||
}
|
||||
|
||||
func (o *gaOperation) rateLimitKey() *RateLimitKey {
|
||||
return &RateLimitKey{
|
||||
ProjectID: o.projectID,
|
||||
Operation: "Get",
|
||||
Service: "Operations",
|
||||
Version: meta.VersionGA,
|
||||
}
|
||||
}
|
||||
|
||||
type alphaOperation struct {
|
||||
s *Service
|
||||
projectID string
|
||||
key *meta.Key
|
||||
}
|
||||
|
||||
func (o *alphaOperation) String() string {
|
||||
return fmt.Sprintf("alphaOperation{%q, %v}", o.projectID, o.key)
|
||||
}
|
||||
|
||||
func (o *alphaOperation) isDone(ctx context.Context) (bool, error) {
|
||||
var (
|
||||
op *alpha.Operation
|
||||
err error
|
||||
)
|
||||
|
||||
switch o.key.Type() {
|
||||
case meta.Regional:
|
||||
op, err = o.s.Alpha.RegionOperations.Get(o.projectID, o.key.Region, o.key.Name).Context(ctx).Do()
|
||||
glog.V(5).Infof("Alpha.RegionOperations.Get(%v, %v, %v) = %+v, %v; ctx = %v", o.projectID, o.key.Region, o.key.Name, op, err, ctx)
|
||||
case meta.Zonal:
|
||||
op, err = o.s.Alpha.ZoneOperations.Get(o.projectID, o.key.Zone, o.key.Name).Context(ctx).Do()
|
||||
glog.V(5).Infof("Alpha.ZoneOperations.Get(%v, %v, %v) = %+v, %v; ctx = %v", o.projectID, o.key.Zone, o.key.Name, op, err, ctx)
|
||||
case meta.Global:
|
||||
op, err = o.s.Alpha.GlobalOperations.Get(o.projectID, o.key.Name).Context(ctx).Do()
|
||||
glog.V(5).Infof("Alpha.GlobalOperations.Get(%v, %v) = %+v, %v; ctx = %v", o.projectID, o.key.Name, op, err, ctx)
|
||||
default:
|
||||
return false, fmt.Errorf("invalid key type: %#v", o.key)
|
||||
}
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
return op != nil && op.Status == "DONE", nil
|
||||
}
|
||||
|
||||
func (o *alphaOperation) rateLimitKey() *RateLimitKey {
|
||||
return &RateLimitKey{
|
||||
ProjectID: o.projectID,
|
||||
Operation: "Get",
|
||||
Service: "Operations",
|
||||
Version: meta.VersionAlpha,
|
||||
}
|
||||
}
|
||||
|
||||
type betaOperation struct {
|
||||
s *Service
|
||||
projectID string
|
||||
key *meta.Key
|
||||
}
|
||||
|
||||
func (o *betaOperation) String() string {
|
||||
return fmt.Sprintf("betaOperation{%q, %v}", o.projectID, o.key)
|
||||
}
|
||||
|
||||
func (o *betaOperation) isDone(ctx context.Context) (bool, error) {
|
||||
var (
|
||||
op *beta.Operation
|
||||
err error
|
||||
)
|
||||
|
||||
switch o.key.Type() {
|
||||
case meta.Regional:
|
||||
op, err = o.s.Beta.RegionOperations.Get(o.projectID, o.key.Region, o.key.Name).Context(ctx).Do()
|
||||
glog.V(5).Infof("Beta.RegionOperations.Get(%v, %v, %v) = %+v, %v; ctx = %v", o.projectID, o.key.Region, o.key.Name, op, err, ctx)
|
||||
case meta.Zonal:
|
||||
op, err = o.s.Beta.ZoneOperations.Get(o.projectID, o.key.Zone, o.key.Name).Context(ctx).Do()
|
||||
glog.V(5).Infof("Beta.ZoneOperations.Get(%v, %v, %v) = %+v, %v; ctx = %v", o.projectID, o.key.Zone, o.key.Name, op, err, ctx)
|
||||
case meta.Global:
|
||||
op, err = o.s.Beta.GlobalOperations.Get(o.projectID, o.key.Name).Context(ctx).Do()
|
||||
glog.V(5).Infof("Beta.GlobalOperations.Get(%v, %v) = %+v, %v; ctx = %v", o.projectID, o.key.Name, op, err, ctx)
|
||||
default:
|
||||
return false, fmt.Errorf("invalid key type: %#v", o.key)
|
||||
}
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
return op != nil && op.Status == "DONE", nil
|
||||
}
|
||||
|
||||
func (o *betaOperation) rateLimitKey() *RateLimitKey {
|
||||
return &RateLimitKey{
|
||||
ProjectID: o.projectID,
|
||||
Operation: "Get",
|
||||
Service: "Operations",
|
||||
Version: meta.VersionBeta,
|
||||
}
|
||||
}
|
45
vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud/project.go
generated
vendored
Normal file
45
vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud/project.go
generated
vendored
Normal file
@ -0,0 +1,45 @@
|
||||
/*
|
||||
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 cloud
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud/meta"
|
||||
)
|
||||
|
||||
// ProjectRouter routes service calls to the appropriate GCE project.
|
||||
type ProjectRouter interface {
|
||||
// ProjectID returns the project ID (non-numeric) to be used for a call
|
||||
// to an API (version,service). Example tuples: ("ga", "ForwardingRules"),
|
||||
// ("alpha", "GlobalAddresses").
|
||||
//
|
||||
// This allows for plumbing different service calls to the appropriate
|
||||
// project, for instance, networking services to a separate project
|
||||
// than instance management.
|
||||
ProjectID(ctx context.Context, version meta.Version, service string) string
|
||||
}
|
||||
|
||||
// SingleProjectRouter routes all service calls to the same project ID.
|
||||
type SingleProjectRouter struct {
|
||||
ID string
|
||||
}
|
||||
|
||||
// ProjectID returns the project ID to be used for a call to the API.
|
||||
func (r *SingleProjectRouter) ProjectID(ctx context.Context, version meta.Version, service string) string {
|
||||
return r.ID
|
||||
}
|
68
vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud/ratelimit.go
generated
vendored
Normal file
68
vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud/ratelimit.go
generated
vendored
Normal file
@ -0,0 +1,68 @@
|
||||
/*
|
||||
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 cloud
|
||||
|
||||
import (
|
||||
"context"
|
||||
"time"
|
||||
|
||||
"k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud/meta"
|
||||
)
|
||||
|
||||
// RateLimitKey is a key identifying the operation to be rate limited. The rate limit
|
||||
// queue will be determined based on the contents of RateKey.
|
||||
type RateLimitKey struct {
|
||||
// ProjectID is the non-numeric ID of the project.
|
||||
ProjectID string
|
||||
// Operation is the specific method being invoked (e.g. "Get", "List").
|
||||
Operation string
|
||||
// Version is the API version of the call.
|
||||
Version meta.Version
|
||||
// Service is the service being invoked (e.g. "Firewalls", "BackendServices")
|
||||
Service string
|
||||
}
|
||||
|
||||
// RateLimiter is the interface for a rate limiting policy.
|
||||
type RateLimiter interface {
|
||||
// Accept uses the RateLimitKey to derive a sleep time for the calling
|
||||
// goroutine. This call will block until the operation is ready for
|
||||
// execution.
|
||||
//
|
||||
// Accept returns an error if the given context ctx was canceled
|
||||
// while waiting for acceptance into the queue.
|
||||
Accept(ctx context.Context, key *RateLimitKey) error
|
||||
}
|
||||
|
||||
// NopRateLimiter is a rate limiter that performs no rate limiting.
|
||||
type NopRateLimiter struct {
|
||||
}
|
||||
|
||||
// Accept the operation to be rate limited.
|
||||
func (*NopRateLimiter) Accept(ctx context.Context, key *RateLimitKey) error {
|
||||
// Rate limit polling of the Operation status to avoid hammering GCE
|
||||
// for the status of an operation.
|
||||
const pollTime = time.Duration(1) * time.Second
|
||||
if key.Operation == "Get" && key.Service == "Operations" {
|
||||
select {
|
||||
case <-time.NewTimer(pollTime).C:
|
||||
break
|
||||
case <-ctx.Done():
|
||||
return ctx.Err()
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
85
vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud/service.go
generated
vendored
Normal file
85
vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud/service.go
generated
vendored
Normal file
@ -0,0 +1,85 @@
|
||||
/*
|
||||
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 cloud
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/golang/glog"
|
||||
|
||||
alpha "google.golang.org/api/compute/v0.alpha"
|
||||
beta "google.golang.org/api/compute/v0.beta"
|
||||
ga "google.golang.org/api/compute/v1"
|
||||
)
|
||||
|
||||
// Service is the top-level adapter for all of the different compute API
|
||||
// versions.
|
||||
type Service struct {
|
||||
GA *ga.Service
|
||||
Alpha *alpha.Service
|
||||
Beta *beta.Service
|
||||
ProjectRouter ProjectRouter
|
||||
RateLimiter RateLimiter
|
||||
}
|
||||
|
||||
// wrapOperation wraps a GCE anyOP in a version generic operation type.
|
||||
func (s *Service) wrapOperation(anyOp interface{}) (operation, error) {
|
||||
switch o := anyOp.(type) {
|
||||
case *ga.Operation:
|
||||
r, err := ParseResourceURL(o.SelfLink)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &gaOperation{s, r.ProjectID, r.Key}, nil
|
||||
case *alpha.Operation:
|
||||
r, err := ParseResourceURL(o.SelfLink)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &alphaOperation{s, r.ProjectID, r.Key}, nil
|
||||
case *beta.Operation:
|
||||
r, err := ParseResourceURL(o.SelfLink)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &betaOperation{s, r.ProjectID, r.Key}, nil
|
||||
default:
|
||||
return nil, fmt.Errorf("invalid type %T", anyOp)
|
||||
}
|
||||
}
|
||||
|
||||
// WaitForCompletion of a long running operation. This will poll the state of
|
||||
// GCE for the completion status of the given operation. genericOp can be one
|
||||
// of alpha, beta, ga Operation types.
|
||||
func (s *Service) WaitForCompletion(ctx context.Context, genericOp interface{}) error {
|
||||
op, err := s.wrapOperation(genericOp)
|
||||
if err != nil {
|
||||
glog.Errorf("wrapOperation(%+v) error: %v", genericOp, err)
|
||||
return err
|
||||
}
|
||||
for done, err := op.isDone(ctx); !done; done, err = op.isDone(ctx) {
|
||||
if err != nil {
|
||||
glog.V(4).Infof("op.isDone(%v) error; op = %v, err = %v", ctx, op, err)
|
||||
return err
|
||||
}
|
||||
glog.V(5).Infof("op.isDone(%v) waiting; op = %v", ctx, op)
|
||||
s.RateLimiter.Accept(ctx, op.rateLimitKey())
|
||||
}
|
||||
glog.V(5).Infof("op.isDone(%v) complete; op = %v", ctx, op)
|
||||
return nil
|
||||
}
|
158
vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud/utils.go
generated
vendored
Normal file
158
vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud/utils.go
generated
vendored
Normal file
@ -0,0 +1,158 @@
|
||||
/*
|
||||
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 cloud
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud/meta"
|
||||
)
|
||||
|
||||
const (
|
||||
gaPrefix = "https://www.googleapis.com/compute/v1/"
|
||||
alphaPrefix = "https://www.googleapis.com/compute/alpha/"
|
||||
betaPrefix = "https://www.googleapis.com/compute/beta/"
|
||||
)
|
||||
|
||||
// ResourceID identifies a GCE resource as parsed from compute resource URL.
|
||||
type ResourceID struct {
|
||||
ProjectID string
|
||||
Resource string
|
||||
Key *meta.Key
|
||||
}
|
||||
|
||||
// Equal returns true if two resource IDs are equal.
|
||||
func (r *ResourceID) Equal(other *ResourceID) bool {
|
||||
if r.ProjectID != other.ProjectID || r.Resource != other.Resource {
|
||||
return false
|
||||
}
|
||||
if r.Key != nil && other.Key != nil {
|
||||
return *r.Key == *other.Key
|
||||
}
|
||||
if r.Key == nil && other.Key == nil {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// ParseResourceURL parses resource URLs of the following formats:
|
||||
//
|
||||
// projects/<proj>/global/<res>/<name>
|
||||
// projects/<proj>/regions/<region>/<res>/<name>
|
||||
// projects/<proj>/zones/<zone>/<res>/<name>
|
||||
// [https://www.googleapis.com/compute/<ver>]/projects/<proj>/global/<res>/<name>
|
||||
// [https://www.googleapis.com/compute/<ver>]/projects/<proj>/regions/<region>/<res>/<name>
|
||||
// [https://www.googleapis.com/compute/<ver>]/projects/<proj>/zones/<zone>/<res>/<name>
|
||||
func ParseResourceURL(url string) (*ResourceID, error) {
|
||||
errNotValid := fmt.Errorf("%q is not a valid resource URL", url)
|
||||
|
||||
// Remove the prefix up to ...projects/
|
||||
projectsIndex := strings.Index(url, "/projects/")
|
||||
if projectsIndex >= 0 {
|
||||
url = url[projectsIndex+1:]
|
||||
}
|
||||
|
||||
parts := strings.Split(url, "/")
|
||||
if len(parts) < 2 || parts[0] != "projects" {
|
||||
return nil, errNotValid
|
||||
}
|
||||
|
||||
ret := &ResourceID{ProjectID: parts[1]}
|
||||
if len(parts) == 2 {
|
||||
ret.Resource = "projects"
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
if len(parts) < 4 {
|
||||
return nil, errNotValid
|
||||
}
|
||||
|
||||
if len(parts) == 4 {
|
||||
switch parts[2] {
|
||||
case "regions":
|
||||
ret.Resource = "regions"
|
||||
ret.Key = meta.GlobalKey(parts[3])
|
||||
return ret, nil
|
||||
case "zones":
|
||||
ret.Resource = "zones"
|
||||
ret.Key = meta.GlobalKey(parts[3])
|
||||
return ret, nil
|
||||
default:
|
||||
return nil, errNotValid
|
||||
}
|
||||
}
|
||||
|
||||
switch parts[2] {
|
||||
case "global":
|
||||
if len(parts) != 5 {
|
||||
return nil, errNotValid
|
||||
}
|
||||
ret.Resource = parts[3]
|
||||
ret.Key = meta.GlobalKey(parts[4])
|
||||
return ret, nil
|
||||
case "regions":
|
||||
if len(parts) != 6 {
|
||||
return nil, errNotValid
|
||||
}
|
||||
ret.Resource = parts[4]
|
||||
ret.Key = meta.RegionalKey(parts[5], parts[3])
|
||||
return ret, nil
|
||||
case "zones":
|
||||
if len(parts) != 6 {
|
||||
return nil, errNotValid
|
||||
}
|
||||
ret.Resource = parts[4]
|
||||
ret.Key = meta.ZonalKey(parts[5], parts[3])
|
||||
return ret, nil
|
||||
}
|
||||
return nil, errNotValid
|
||||
}
|
||||
|
||||
func copyViaJSON(dest, src interface{}) error {
|
||||
bytes, err := json.Marshal(src)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return json.Unmarshal(bytes, dest)
|
||||
}
|
||||
|
||||
// SelfLink returns the self link URL for the given object.
|
||||
func SelfLink(ver meta.Version, project, resource string, key *meta.Key) string {
|
||||
var prefix string
|
||||
switch ver {
|
||||
case meta.VersionAlpha:
|
||||
prefix = alphaPrefix
|
||||
case meta.VersionBeta:
|
||||
prefix = betaPrefix
|
||||
case meta.VersionGA:
|
||||
prefix = gaPrefix
|
||||
default:
|
||||
prefix = "invalid-prefix"
|
||||
}
|
||||
|
||||
switch key.Type() {
|
||||
case meta.Zonal:
|
||||
return fmt.Sprintf("%sprojects/%s/zones/%s/%s/%s", prefix, project, key.Zone, resource, key.Name)
|
||||
case meta.Regional:
|
||||
return fmt.Sprintf("%sprojects/%s/regions/%s/%s/%s", prefix, project, key.Region, resource, key.Name)
|
||||
case meta.Global:
|
||||
return fmt.Sprintf("%sprojects/%s/%s/%s", prefix, project, resource, key.Name)
|
||||
}
|
||||
return "invalid-self-link"
|
||||
}
|
208
vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud/utils_test.go
generated
vendored
Normal file
208
vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud/utils_test.go
generated
vendored
Normal file
@ -0,0 +1,208 @@
|
||||
/*
|
||||
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 cloud
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"testing"
|
||||
|
||||
"k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud/meta"
|
||||
)
|
||||
|
||||
func TestParseResourceURL(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
for _, tc := range []struct {
|
||||
in string
|
||||
r *ResourceID
|
||||
}{
|
||||
{
|
||||
"https://www.googleapis.com/compute/v1/projects/some-gce-project",
|
||||
&ResourceID{"some-gce-project", "projects", nil},
|
||||
},
|
||||
{
|
||||
"https://www.googleapis.com/compute/v1/projects/some-gce-project/regions/us-central1",
|
||||
&ResourceID{"some-gce-project", "regions", meta.GlobalKey("us-central1")},
|
||||
},
|
||||
{
|
||||
"https://www.googleapis.com/compute/v1/projects/some-gce-project/zones/us-central1-b",
|
||||
&ResourceID{"some-gce-project", "zones", meta.GlobalKey("us-central1-b")},
|
||||
},
|
||||
{
|
||||
"https://www.googleapis.com/compute/v1/projects/some-gce-project/global/operations/operation-1513289952196-56054460af5a0-b1dae0c3-9bbf9dbf",
|
||||
&ResourceID{"some-gce-project", "operations", meta.GlobalKey("operation-1513289952196-56054460af5a0-b1dae0c3-9bbf9dbf")},
|
||||
},
|
||||
{
|
||||
"https://www.googleapis.com/compute/alpha/projects/some-gce-project/regions/us-central1/addresses/my-address",
|
||||
&ResourceID{"some-gce-project", "addresses", meta.RegionalKey("my-address", "us-central1")},
|
||||
},
|
||||
{
|
||||
"https://www.googleapis.com/compute/v1/projects/some-gce-project/zones/us-central1-c/instances/instance-1",
|
||||
&ResourceID{"some-gce-project", "instances", meta.ZonalKey("instance-1", "us-central1-c")},
|
||||
},
|
||||
{
|
||||
"http://localhost:3990/compute/beta/projects/some-gce-project/global/operations/operation-1513289952196-56054460af5a0-b1dae0c3-9bbf9dbf",
|
||||
&ResourceID{"some-gce-project", "operations", meta.GlobalKey("operation-1513289952196-56054460af5a0-b1dae0c3-9bbf9dbf")},
|
||||
},
|
||||
{
|
||||
"http://localhost:3990/compute/alpha/projects/some-gce-project/regions/dev-central1/addresses/my-address",
|
||||
&ResourceID{"some-gce-project", "addresses", meta.RegionalKey("my-address", "dev-central1")},
|
||||
},
|
||||
{
|
||||
"http://localhost:3990/compute/v1/projects/some-gce-project/zones/dev-central1-std/instances/instance-1",
|
||||
&ResourceID{"some-gce-project", "instances", meta.ZonalKey("instance-1", "dev-central1-std")},
|
||||
},
|
||||
{
|
||||
"projects/some-gce-project",
|
||||
&ResourceID{"some-gce-project", "projects", nil},
|
||||
},
|
||||
{
|
||||
"projects/some-gce-project/regions/us-central1",
|
||||
&ResourceID{"some-gce-project", "regions", meta.GlobalKey("us-central1")},
|
||||
},
|
||||
{
|
||||
"projects/some-gce-project/zones/us-central1-b",
|
||||
&ResourceID{"some-gce-project", "zones", meta.GlobalKey("us-central1-b")},
|
||||
},
|
||||
{
|
||||
"projects/some-gce-project/global/operations/operation-1513289952196-56054460af5a0-b1dae0c3-9bbf9dbf",
|
||||
&ResourceID{"some-gce-project", "operations", meta.GlobalKey("operation-1513289952196-56054460af5a0-b1dae0c3-9bbf9dbf")},
|
||||
},
|
||||
{
|
||||
"projects/some-gce-project/regions/us-central1/addresses/my-address",
|
||||
&ResourceID{"some-gce-project", "addresses", meta.RegionalKey("my-address", "us-central1")},
|
||||
},
|
||||
{
|
||||
"projects/some-gce-project/zones/us-central1-c/instances/instance-1",
|
||||
&ResourceID{"some-gce-project", "instances", meta.ZonalKey("instance-1", "us-central1-c")},
|
||||
},
|
||||
} {
|
||||
r, err := ParseResourceURL(tc.in)
|
||||
if err != nil {
|
||||
t.Errorf("ParseResourceURL(%q) = %+v, %v; want _, nil", tc.in, r, err)
|
||||
continue
|
||||
}
|
||||
if !r.Equal(tc.r) {
|
||||
t.Errorf("ParseResourceURL(%q) = %+v, nil; want %+v, nil", tc.in, r, tc.r)
|
||||
}
|
||||
}
|
||||
// Malformed URLs.
|
||||
for _, tc := range []string{
|
||||
"",
|
||||
"/",
|
||||
"/a",
|
||||
"/a/b",
|
||||
"/a/b/c",
|
||||
"/a/b/c/d",
|
||||
"/a/b/c/d/e",
|
||||
"/a/b/c/d/e/f",
|
||||
"https://www.googleapis.com/compute/v1/projects/some-gce-project/global",
|
||||
"projects/some-gce-project/global",
|
||||
"projects/some-gce-project/global/foo/bar/baz",
|
||||
"projects/some-gce-project/zones/us-central1-c/res",
|
||||
"projects/some-gce-project/zones/us-central1-c/res/name/extra",
|
||||
} {
|
||||
r, err := ParseResourceURL(tc)
|
||||
if err == nil {
|
||||
t.Errorf("ParseResourceURL(%q) = %+v, %v, want _, error", tc, r, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
type A struct {
|
||||
A, B, C string
|
||||
}
|
||||
|
||||
type B struct {
|
||||
A, B, D string
|
||||
}
|
||||
|
||||
type E struct{}
|
||||
|
||||
func (*E) MarshalJSON() ([]byte, error) {
|
||||
return nil, errors.New("injected error")
|
||||
}
|
||||
|
||||
func TestCopyVisJSON(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
var b B
|
||||
srcA := &A{"aa", "bb", "cc"}
|
||||
err := copyViaJSON(&b, srcA)
|
||||
if err != nil {
|
||||
t.Errorf(`copyViaJSON(&b, %+v) = %v, want nil`, srcA, err)
|
||||
} else {
|
||||
expectedB := B{"aa", "bb", ""}
|
||||
if b != expectedB {
|
||||
t.Errorf("b == %+v, want %+v", b, expectedB)
|
||||
}
|
||||
}
|
||||
|
||||
var a A
|
||||
srcB := &B{"aaa", "bbb", "ccc"}
|
||||
err = copyViaJSON(&a, srcB)
|
||||
if err != nil {
|
||||
t.Errorf(`copyViaJSON(&a, %+v) = %v, want nil`, srcB, err)
|
||||
} else {
|
||||
expectedA := A{"aaa", "bbb", ""}
|
||||
if a != expectedA {
|
||||
t.Errorf("a == %+v, want %+v", a, expectedA)
|
||||
}
|
||||
}
|
||||
|
||||
if err := copyViaJSON(&a, &E{}); err == nil {
|
||||
t.Errorf("copyViaJSON(&a, &E{}) = nil, want error")
|
||||
}
|
||||
}
|
||||
|
||||
func TestSelfLink(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
for _, tc := range []struct {
|
||||
ver meta.Version
|
||||
project string
|
||||
resource string
|
||||
key *meta.Key
|
||||
want string
|
||||
}{
|
||||
{
|
||||
meta.VersionAlpha,
|
||||
"proj1",
|
||||
"addresses",
|
||||
meta.RegionalKey("key1", "us-central1"),
|
||||
"https://www.googleapis.com/compute/alpha/projects/proj1/regions/us-central1/addresses/key1",
|
||||
},
|
||||
{
|
||||
meta.VersionBeta,
|
||||
"proj3",
|
||||
"disks",
|
||||
meta.ZonalKey("key2", "us-central1-b"),
|
||||
"https://www.googleapis.com/compute/beta/projects/proj3/zones/us-central1-b/disks/key2",
|
||||
},
|
||||
{
|
||||
meta.VersionGA,
|
||||
"proj4",
|
||||
"urlMaps",
|
||||
meta.GlobalKey("key3"),
|
||||
"https://www.googleapis.com/compute/v1/projects/proj4/urlMaps/key3",
|
||||
},
|
||||
} {
|
||||
if link := SelfLink(tc.ver, tc.project, tc.resource, tc.key); link != tc.want {
|
||||
t.Errorf("SelfLink(%v, %q, %q, %v) = %v, want %q", tc.ver, tc.project, tc.resource, tc.key, link, tc.want)
|
||||
}
|
||||
}
|
||||
}
|
98
vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/gce.go
generated
vendored
98
vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/gce.go
generated
vendored
@ -21,7 +21,6 @@ import (
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"regexp"
|
||||
"runtime"
|
||||
"strconv"
|
||||
"strings"
|
||||
@ -31,6 +30,13 @@ import (
|
||||
gcfg "gopkg.in/gcfg.v1"
|
||||
|
||||
"cloud.google.com/go/compute/metadata"
|
||||
"github.com/golang/glog"
|
||||
"golang.org/x/oauth2"
|
||||
"golang.org/x/oauth2/google"
|
||||
computealpha "google.golang.org/api/compute/v0.alpha"
|
||||
computebeta "google.golang.org/api/compute/v0.beta"
|
||||
compute "google.golang.org/api/compute/v1"
|
||||
container "google.golang.org/api/container/v1"
|
||||
|
||||
"k8s.io/api/core/v1"
|
||||
"k8s.io/apimachinery/pkg/util/sets"
|
||||
@ -42,18 +48,12 @@ import (
|
||||
"k8s.io/client-go/tools/cache"
|
||||
"k8s.io/client-go/tools/record"
|
||||
"k8s.io/client-go/util/flowcontrol"
|
||||
|
||||
"k8s.io/kubernetes/pkg/cloudprovider"
|
||||
"k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud"
|
||||
"k8s.io/kubernetes/pkg/controller"
|
||||
kubeletapis "k8s.io/kubernetes/pkg/kubelet/apis"
|
||||
"k8s.io/kubernetes/pkg/version"
|
||||
|
||||
"github.com/golang/glog"
|
||||
"golang.org/x/oauth2"
|
||||
"golang.org/x/oauth2/google"
|
||||
computealpha "google.golang.org/api/compute/v0.alpha"
|
||||
computebeta "google.golang.org/api/compute/v0.beta"
|
||||
compute "google.golang.org/api/compute/v1"
|
||||
container "google.golang.org/api/container/v1"
|
||||
)
|
||||
|
||||
const (
|
||||
@ -107,6 +107,7 @@ type GCECloud struct {
|
||||
serviceBeta *computebeta.Service
|
||||
serviceAlpha *computealpha.Service
|
||||
containerService *container.Service
|
||||
tpuService *tpuService
|
||||
client clientset.Interface
|
||||
clientBuilder controller.ControllerClientBuilder
|
||||
eventBroadcaster record.EventBroadcaster
|
||||
@ -148,6 +149,9 @@ type GCECloud struct {
|
||||
// the corresponding api is enabled.
|
||||
// If not enabled, it should return error.
|
||||
AlphaFeatureGate *AlphaFeatureGate
|
||||
|
||||
// New code generated interface to the GCE compute library.
|
||||
c cloud.Cloud
|
||||
}
|
||||
|
||||
// TODO: replace gcfg with json
|
||||
@ -213,9 +217,22 @@ func init() {
|
||||
})
|
||||
}
|
||||
|
||||
// Raw access to the underlying GCE service, probably should only be used for e2e tests
|
||||
func (g *GCECloud) GetComputeService() *compute.Service {
|
||||
return g.service
|
||||
// Services is the set of all versions of the compute service.
|
||||
type Services struct {
|
||||
// GA, Alpha, Beta versions of the compute API.
|
||||
GA *compute.Service
|
||||
Alpha *computealpha.Service
|
||||
Beta *computebeta.Service
|
||||
}
|
||||
|
||||
// ComputeServices returns access to the internal compute services.
|
||||
func (g *GCECloud) ComputeServices() *Services {
|
||||
return &Services{g.service, g.serviceAlpha, g.serviceBeta}
|
||||
}
|
||||
|
||||
// Compute returns the generated stubs for the compute API.
|
||||
func (g *GCECloud) Compute() cloud.Cloud {
|
||||
return g.c
|
||||
}
|
||||
|
||||
// newGCECloud creates a new instance of GCECloud.
|
||||
@ -236,7 +253,6 @@ func newGCECloud(config io.Reader) (gceCloud *GCECloud, err error) {
|
||||
return nil, err
|
||||
}
|
||||
return CreateGCECloud(cloudConfig)
|
||||
|
||||
}
|
||||
|
||||
func readConfig(reader io.Reader) (*ConfigFile, error) {
|
||||
@ -356,11 +372,12 @@ func generateCloudConfig(configFile *ConfigFile) (cloudConfig *CloudConfig, err
|
||||
// If no tokenSource is specified, uses oauth2.DefaultTokenSource.
|
||||
// If managedZones is nil / empty all zones in the region will be managed.
|
||||
func CreateGCECloud(config *CloudConfig) (*GCECloud, error) {
|
||||
// Remove any pre-release version and build metadata from the semver, leaving only the MAJOR.MINOR.PATCH portion.
|
||||
// See http://semver.org/.
|
||||
// Remove any pre-release version and build metadata from the semver,
|
||||
// leaving only the MAJOR.MINOR.PATCH portion. See http://semver.org/.
|
||||
version := strings.TrimLeft(strings.Split(strings.Split(version.Get().GitVersion, "-")[0], "+")[0], "v")
|
||||
|
||||
// Create a user-agent header append string to supply to the Google API clients, to identify Kubernetes as the origin of the GCP API calls.
|
||||
// Create a user-agent header append string to supply to the Google API
|
||||
// clients, to identify Kubernetes as the origin of the GCP API calls.
|
||||
userAgent := fmt.Sprintf("Kubernetes/%s (%s %s)", version, runtime.GOOS, runtime.GOARCH)
|
||||
|
||||
// Use ProjectID for NetworkProjectID, if it wasn't explicitly set.
|
||||
@ -414,6 +431,11 @@ func CreateGCECloud(config *CloudConfig) (*GCECloud, error) {
|
||||
}
|
||||
containerService.UserAgent = userAgent
|
||||
|
||||
tpuService, err := newTPUService(client)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// ProjectID and.NetworkProjectID may be project number or name.
|
||||
projID, netProjID := tryConvertToProjectNames(config.ProjectID, config.NetworkProjectID, service)
|
||||
onXPN := projID != netProjID
|
||||
@ -480,6 +502,7 @@ func CreateGCECloud(config *CloudConfig) (*GCECloud, error) {
|
||||
serviceAlpha: serviceAlpha,
|
||||
serviceBeta: serviceBeta,
|
||||
containerService: containerService,
|
||||
tpuService: tpuService,
|
||||
projectID: projID,
|
||||
networkProjectID: netProjID,
|
||||
onXPN: onXPN,
|
||||
@ -499,6 +522,13 @@ func CreateGCECloud(config *CloudConfig) (*GCECloud, error) {
|
||||
}
|
||||
|
||||
gce.manager = &gceServiceManager{gce}
|
||||
gce.c = cloud.NewGCE(&cloud.Service{
|
||||
GA: service,
|
||||
Alpha: serviceAlpha,
|
||||
Beta: serviceBeta,
|
||||
ProjectRouter: &gceProjectRouter{gce},
|
||||
RateLimiter: &gceRateLimiter{gce},
|
||||
})
|
||||
|
||||
return gce, nil
|
||||
}
|
||||
@ -694,20 +724,6 @@ func (gce *GCECloud) updateNodeZones(prevNode, newNode *v1.Node) {
|
||||
}
|
||||
}
|
||||
|
||||
// Known-useless DNS search path.
|
||||
var uselessDNSSearchRE = regexp.MustCompile(`^[0-9]+.google.internal.$`)
|
||||
|
||||
// ScrubDNS filters DNS settings for pods.
|
||||
func (gce *GCECloud) ScrubDNS(nameservers, searches []string) (nsOut, srchOut []string) {
|
||||
// GCE has too many search paths by default. Filter the ones we know are useless.
|
||||
for _, s := range searches {
|
||||
if !uselessDNSSearchRE.MatchString(s) {
|
||||
srchOut = append(srchOut, s)
|
||||
}
|
||||
}
|
||||
return nameservers, srchOut
|
||||
}
|
||||
|
||||
// HasClusterID returns true if the cluster has a clusterID
|
||||
func (gce *GCECloud) HasClusterID() bool {
|
||||
return true
|
||||
@ -737,20 +753,6 @@ func gceSubnetworkURL(apiEndpoint, project, region, subnetwork string) string {
|
||||
return apiEndpoint + strings.Join([]string{"projects", project, "regions", region, "subnetworks", subnetwork}, "/")
|
||||
}
|
||||
|
||||
// getProjectIDInURL parses full resource URLS and shorter URLS
|
||||
// https://www.googleapis.com/compute/v1/projects/myproject/global/networks/mycustom
|
||||
// projects/myproject/global/networks/mycustom
|
||||
// All return "myproject"
|
||||
func getProjectIDInURL(urlStr string) (string, error) {
|
||||
fields := strings.Split(urlStr, "/")
|
||||
for i, v := range fields {
|
||||
if v == "projects" && i < len(fields)-1 {
|
||||
return fields[i+1], nil
|
||||
}
|
||||
}
|
||||
return "", fmt.Errorf("could not find project field in url: %v", urlStr)
|
||||
}
|
||||
|
||||
// getRegionInURL parses full resource URLS and shorter URLS
|
||||
// https://www.googleapis.com/compute/v1/projects/myproject/regions/us-central1/subnetworks/a
|
||||
// projects/myproject/regions/us-central1/subnetworks/a
|
||||
@ -848,7 +850,13 @@ func newOauthClient(tokenSource oauth2.TokenSource) (*http.Client, error) {
|
||||
glog.Infof("Using existing Token Source %#v", tokenSource)
|
||||
}
|
||||
|
||||
if err := wait.PollImmediate(5*time.Second, 30*time.Second, func() (bool, error) {
|
||||
backoff := wait.Backoff{
|
||||
// These values will add up to about a minute. See #56293 for background.
|
||||
Duration: time.Second,
|
||||
Factor: 1.4,
|
||||
Steps: 10,
|
||||
}
|
||||
if err := wait.ExponentialBackoff(backoff, func() (bool, error) {
|
||||
if _, err := tokenSource.Token(); err != nil {
|
||||
glog.Errorf("error fetching initial token: %v", err)
|
||||
return false, nil
|
||||
|
19
vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/gce_address_manager.go
generated
vendored
19
vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/gce_address_manager.go
generated
vendored
@ -20,9 +20,10 @@ import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
|
||||
computebeta "google.golang.org/api/compute/v0.beta"
|
||||
compute "google.golang.org/api/compute/v1"
|
||||
|
||||
"github.com/golang/glog"
|
||||
"k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud"
|
||||
)
|
||||
|
||||
type addressManager struct {
|
||||
@ -31,13 +32,13 @@ type addressManager struct {
|
||||
name string
|
||||
serviceName string
|
||||
targetIP string
|
||||
addressType lbScheme
|
||||
addressType cloud.LbScheme
|
||||
region string
|
||||
subnetURL string
|
||||
tryRelease bool
|
||||
}
|
||||
|
||||
func newAddressManager(svc CloudAddressService, serviceName, region, subnetURL, name, targetIP string, addressType lbScheme) *addressManager {
|
||||
func newAddressManager(svc CloudAddressService, serviceName, region, subnetURL, name, targetIP string, addressType cloud.LbScheme) *addressManager {
|
||||
return &addressManager{
|
||||
svc: svc,
|
||||
logPrefix: fmt.Sprintf("AddressManager(%q)", name),
|
||||
@ -63,7 +64,7 @@ func (am *addressManager) HoldAddress() (string, error) {
|
||||
// calls since it indicates whether a Delete is necessary before Reserve.
|
||||
glog.V(4).Infof("%v: attempting hold of IP %q Type %q", am.logPrefix, am.targetIP, am.addressType)
|
||||
// Get the address in case it was orphaned earlier
|
||||
addr, err := am.svc.GetBetaRegionAddress(am.name, am.region)
|
||||
addr, err := am.svc.GetRegionAddress(am.name, am.region)
|
||||
if err != nil && !isNotFound(err) {
|
||||
return "", err
|
||||
}
|
||||
@ -118,7 +119,7 @@ func (am *addressManager) ReleaseAddress() error {
|
||||
func (am *addressManager) ensureAddressReservation() (string, error) {
|
||||
// Try reserving the IP with controller-owned address name
|
||||
// If am.targetIP is an empty string, a new IP will be created.
|
||||
newAddr := &computebeta.Address{
|
||||
newAddr := &compute.Address{
|
||||
Name: am.name,
|
||||
Description: fmt.Sprintf(`{"kubernetes.io/service-name":"%s"}`, am.serviceName),
|
||||
Address: am.targetIP,
|
||||
@ -126,7 +127,7 @@ func (am *addressManager) ensureAddressReservation() (string, error) {
|
||||
Subnetwork: am.subnetURL,
|
||||
}
|
||||
|
||||
reserveErr := am.svc.ReserveBetaRegionAddress(newAddr, am.region)
|
||||
reserveErr := am.svc.ReserveRegionAddress(newAddr, am.region)
|
||||
if reserveErr == nil {
|
||||
if newAddr.Address != "" {
|
||||
glog.V(4).Infof("%v: successfully reserved IP %q with name %q", am.logPrefix, newAddr.Address, newAddr.Name)
|
||||
@ -155,7 +156,7 @@ func (am *addressManager) ensureAddressReservation() (string, error) {
|
||||
|
||||
// Reserving the address failed due to a conflict or bad request. The address manager just checked that no address
|
||||
// exists with the name, so it may belong to the user.
|
||||
addr, err := am.svc.GetBetaRegionAddressByIP(am.region, am.targetIP)
|
||||
addr, err := am.svc.GetRegionAddressByIP(am.region, am.targetIP)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("failed to get address by IP %q after reservation attempt, err: %q, reservation err: %q", am.targetIP, err, reserveErr)
|
||||
}
|
||||
@ -178,7 +179,7 @@ func (am *addressManager) ensureAddressReservation() (string, error) {
|
||||
return addr.Address, nil
|
||||
}
|
||||
|
||||
func (am *addressManager) validateAddress(addr *computebeta.Address) error {
|
||||
func (am *addressManager) validateAddress(addr *compute.Address) error {
|
||||
if am.targetIP != "" && am.targetIP != addr.Address {
|
||||
return fmt.Errorf("address %q does not have the expected IP %q, actual: %q", addr.Name, am.targetIP, addr.Address)
|
||||
}
|
||||
@ -189,7 +190,7 @@ func (am *addressManager) validateAddress(addr *computebeta.Address) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (am *addressManager) isManagedAddress(addr *computebeta.Address) bool {
|
||||
func (am *addressManager) isManagedAddress(addr *compute.Address) bool {
|
||||
return addr.Name == am.name
|
||||
}
|
||||
|
||||
|
43
vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/gce_address_manager_test.go
generated
vendored
43
vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/gce_address_manager_test.go
generated
vendored
@ -21,7 +21,8 @@ import (
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
computebeta "google.golang.org/api/compute/v0.beta"
|
||||
compute "google.golang.org/api/compute/v1"
|
||||
"k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud"
|
||||
)
|
||||
|
||||
const testSvcName = "my-service"
|
||||
@ -34,8 +35,8 @@ func TestAddressManagerNoRequestedIP(t *testing.T) {
|
||||
svc := NewFakeCloudAddressService()
|
||||
targetIP := ""
|
||||
|
||||
mgr := newAddressManager(svc, testSvcName, testRegion, testSubnet, testLBName, targetIP, schemeInternal)
|
||||
testHoldAddress(t, mgr, svc, testLBName, testRegion, targetIP, string(schemeInternal))
|
||||
mgr := newAddressManager(svc, testSvcName, testRegion, testSubnet, testLBName, targetIP, cloud.SchemeInternal)
|
||||
testHoldAddress(t, mgr, svc, testLBName, testRegion, targetIP, string(cloud.SchemeInternal))
|
||||
testReleaseAddress(t, mgr, svc, testLBName, testRegion)
|
||||
}
|
||||
|
||||
@ -44,8 +45,8 @@ func TestAddressManagerBasic(t *testing.T) {
|
||||
svc := NewFakeCloudAddressService()
|
||||
targetIP := "1.1.1.1"
|
||||
|
||||
mgr := newAddressManager(svc, testSvcName, testRegion, testSubnet, testLBName, targetIP, schemeInternal)
|
||||
testHoldAddress(t, mgr, svc, testLBName, testRegion, targetIP, string(schemeInternal))
|
||||
mgr := newAddressManager(svc, testSvcName, testRegion, testSubnet, testLBName, targetIP, cloud.SchemeInternal)
|
||||
testHoldAddress(t, mgr, svc, testLBName, testRegion, targetIP, string(cloud.SchemeInternal))
|
||||
testReleaseAddress(t, mgr, svc, testLBName, testRegion)
|
||||
}
|
||||
|
||||
@ -55,12 +56,12 @@ func TestAddressManagerOrphaned(t *testing.T) {
|
||||
svc := NewFakeCloudAddressService()
|
||||
targetIP := "1.1.1.1"
|
||||
|
||||
addr := &computebeta.Address{Name: testLBName, Address: targetIP, AddressType: string(schemeInternal)}
|
||||
err := svc.ReserveBetaRegionAddress(addr, testRegion)
|
||||
addr := &compute.Address{Name: testLBName, Address: targetIP, AddressType: string(cloud.SchemeInternal)}
|
||||
err := svc.ReserveRegionAddress(addr, testRegion)
|
||||
require.NoError(t, err)
|
||||
|
||||
mgr := newAddressManager(svc, testSvcName, testRegion, testSubnet, testLBName, targetIP, schemeInternal)
|
||||
testHoldAddress(t, mgr, svc, testLBName, testRegion, targetIP, string(schemeInternal))
|
||||
mgr := newAddressManager(svc, testSvcName, testRegion, testSubnet, testLBName, targetIP, cloud.SchemeInternal)
|
||||
testHoldAddress(t, mgr, svc, testLBName, testRegion, targetIP, string(cloud.SchemeInternal))
|
||||
testReleaseAddress(t, mgr, svc, testLBName, testRegion)
|
||||
}
|
||||
|
||||
@ -71,12 +72,12 @@ func TestAddressManagerOutdatedOrphan(t *testing.T) {
|
||||
previousAddress := "1.1.0.0"
|
||||
targetIP := "1.1.1.1"
|
||||
|
||||
addr := &computebeta.Address{Name: testLBName, Address: previousAddress, AddressType: string(schemeExternal)}
|
||||
err := svc.ReserveBetaRegionAddress(addr, testRegion)
|
||||
addr := &compute.Address{Name: testLBName, Address: previousAddress, AddressType: string(cloud.SchemeExternal)}
|
||||
err := svc.ReserveRegionAddress(addr, testRegion)
|
||||
require.NoError(t, err)
|
||||
|
||||
mgr := newAddressManager(svc, testSvcName, testRegion, testSubnet, testLBName, targetIP, schemeInternal)
|
||||
testHoldAddress(t, mgr, svc, testLBName, testRegion, targetIP, string(schemeInternal))
|
||||
mgr := newAddressManager(svc, testSvcName, testRegion, testSubnet, testLBName, targetIP, cloud.SchemeInternal)
|
||||
testHoldAddress(t, mgr, svc, testLBName, testRegion, targetIP, string(cloud.SchemeInternal))
|
||||
testReleaseAddress(t, mgr, svc, testLBName, testRegion)
|
||||
}
|
||||
|
||||
@ -86,11 +87,11 @@ func TestAddressManagerExternallyOwned(t *testing.T) {
|
||||
svc := NewFakeCloudAddressService()
|
||||
targetIP := "1.1.1.1"
|
||||
|
||||
addr := &computebeta.Address{Name: "my-important-address", Address: targetIP, AddressType: string(schemeInternal)}
|
||||
err := svc.ReserveBetaRegionAddress(addr, testRegion)
|
||||
addr := &compute.Address{Name: "my-important-address", Address: targetIP, AddressType: string(cloud.SchemeInternal)}
|
||||
err := svc.ReserveRegionAddress(addr, testRegion)
|
||||
require.NoError(t, err)
|
||||
|
||||
mgr := newAddressManager(svc, testSvcName, testRegion, testSubnet, testLBName, targetIP, schemeInternal)
|
||||
mgr := newAddressManager(svc, testSvcName, testRegion, testSubnet, testLBName, targetIP, cloud.SchemeInternal)
|
||||
ipToUse, err := mgr.HoldAddress()
|
||||
require.NoError(t, err)
|
||||
assert.NotEmpty(t, ipToUse)
|
||||
@ -107,11 +108,11 @@ func TestAddressManagerBadExternallyOwned(t *testing.T) {
|
||||
svc := NewFakeCloudAddressService()
|
||||
targetIP := "1.1.1.1"
|
||||
|
||||
addr := &computebeta.Address{Name: "my-important-address", Address: targetIP, AddressType: string(schemeExternal)}
|
||||
err := svc.ReserveBetaRegionAddress(addr, testRegion)
|
||||
addr := &compute.Address{Name: "my-important-address", Address: targetIP, AddressType: string(cloud.SchemeExternal)}
|
||||
err := svc.ReserveRegionAddress(addr, testRegion)
|
||||
require.NoError(t, err)
|
||||
|
||||
mgr := newAddressManager(svc, testSvcName, testRegion, testSubnet, testLBName, targetIP, schemeInternal)
|
||||
mgr := newAddressManager(svc, testSvcName, testRegion, testSubnet, testLBName, targetIP, cloud.SchemeInternal)
|
||||
_, err = mgr.HoldAddress()
|
||||
assert.NotNil(t, err)
|
||||
}
|
||||
@ -121,7 +122,7 @@ func testHoldAddress(t *testing.T, mgr *addressManager, svc CloudAddressService,
|
||||
require.NoError(t, err)
|
||||
assert.NotEmpty(t, ipToUse)
|
||||
|
||||
addr, err := svc.GetBetaRegionAddress(name, region)
|
||||
addr, err := svc.GetRegionAddress(name, region)
|
||||
require.NoError(t, err)
|
||||
if targetIP != "" {
|
||||
assert.EqualValues(t, targetIP, addr.Address)
|
||||
@ -132,6 +133,6 @@ func testHoldAddress(t *testing.T, mgr *addressManager, svc CloudAddressService,
|
||||
func testReleaseAddress(t *testing.T, mgr *addressManager, svc CloudAddressService, name, region string) {
|
||||
err := mgr.ReleaseAddress()
|
||||
require.NoError(t, err)
|
||||
_, err = svc.GetBetaRegionAddress(name, region)
|
||||
_, err = svc.GetRegionAddress(name, region)
|
||||
assert.True(t, isNotFound(err))
|
||||
}
|
||||
|
104
vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/gce_addresses.go
generated
vendored
104
vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/gce_addresses.go
generated
vendored
@ -17,6 +17,7 @@ limitations under the License.
|
||||
package gce
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/golang/glog"
|
||||
@ -24,6 +25,10 @@ import (
|
||||
computealpha "google.golang.org/api/compute/v0.alpha"
|
||||
computebeta "google.golang.org/api/compute/v0.beta"
|
||||
compute "google.golang.org/api/compute/v1"
|
||||
|
||||
"k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud"
|
||||
"k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud/filter"
|
||||
"k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud/meta"
|
||||
)
|
||||
|
||||
func newAddressMetricContext(request, region string) *metricContext {
|
||||
@ -40,110 +45,81 @@ func newAddressMetricContextWithVersion(request, region, version string) *metric
|
||||
// ephemeral IP associated with a global forwarding rule.
|
||||
func (gce *GCECloud) ReserveGlobalAddress(addr *compute.Address) error {
|
||||
mc := newAddressMetricContext("reserve", "")
|
||||
op, err := gce.service.GlobalAddresses.Insert(gce.projectID, addr).Do()
|
||||
if err != nil {
|
||||
return mc.Observe(err)
|
||||
}
|
||||
return gce.waitForGlobalOp(op, mc)
|
||||
return mc.Observe(gce.c.GlobalAddresses().Insert(context.Background(), meta.GlobalKey(addr.Name), addr))
|
||||
}
|
||||
|
||||
// DeleteGlobalAddress deletes a global address by name.
|
||||
func (gce *GCECloud) DeleteGlobalAddress(name string) error {
|
||||
mc := newAddressMetricContext("delete", "")
|
||||
op, err := gce.service.GlobalAddresses.Delete(gce.projectID, name).Do()
|
||||
if err != nil {
|
||||
return mc.Observe(err)
|
||||
}
|
||||
return gce.waitForGlobalOp(op, mc)
|
||||
return mc.Observe(gce.c.GlobalAddresses().Delete(context.Background(), meta.GlobalKey(name)))
|
||||
}
|
||||
|
||||
// GetGlobalAddress returns the global address by name.
|
||||
func (gce *GCECloud) GetGlobalAddress(name string) (*compute.Address, error) {
|
||||
mc := newAddressMetricContext("get", "")
|
||||
v, err := gce.service.GlobalAddresses.Get(gce.projectID, name).Do()
|
||||
v, err := gce.c.GlobalAddresses().Get(context.Background(), meta.GlobalKey(name))
|
||||
return v, mc.Observe(err)
|
||||
}
|
||||
|
||||
// ReserveRegionAddress creates a region address
|
||||
func (gce *GCECloud) ReserveRegionAddress(addr *compute.Address, region string) error {
|
||||
mc := newAddressMetricContext("reserve", region)
|
||||
op, err := gce.service.Addresses.Insert(gce.projectID, region, addr).Do()
|
||||
if err != nil {
|
||||
return mc.Observe(err)
|
||||
}
|
||||
return gce.waitForRegionOp(op, region, mc)
|
||||
return mc.Observe(gce.c.Addresses().Insert(context.Background(), meta.RegionalKey(addr.Name, region), addr))
|
||||
}
|
||||
|
||||
// ReserveAlphaRegionAddress creates an Alpha, regional address.
|
||||
func (gce *GCECloud) ReserveAlphaRegionAddress(addr *computealpha.Address, region string) error {
|
||||
mc := newAddressMetricContextWithVersion("reserve", region, computeAlphaVersion)
|
||||
op, err := gce.serviceAlpha.Addresses.Insert(gce.projectID, region, addr).Do()
|
||||
if err != nil {
|
||||
return mc.Observe(err)
|
||||
}
|
||||
return gce.waitForRegionOp(op, region, mc)
|
||||
mc := newAddressMetricContext("reserve", region)
|
||||
return mc.Observe(gce.c.AlphaAddresses().Insert(context.Background(), meta.RegionalKey(addr.Name, region), addr))
|
||||
}
|
||||
|
||||
// ReserveBetaRegionAddress creates a beta region address
|
||||
func (gce *GCECloud) ReserveBetaRegionAddress(addr *computebeta.Address, region string) error {
|
||||
mc := newAddressMetricContextWithVersion("reserve", region, computeBetaVersion)
|
||||
op, err := gce.serviceBeta.Addresses.Insert(gce.projectID, region, addr).Do()
|
||||
if err != nil {
|
||||
return mc.Observe(err)
|
||||
}
|
||||
return gce.waitForRegionOp(op, region, mc)
|
||||
mc := newAddressMetricContext("reserve", region)
|
||||
return mc.Observe(gce.c.BetaAddresses().Insert(context.Background(), meta.RegionalKey(addr.Name, region), addr))
|
||||
}
|
||||
|
||||
// DeleteRegionAddress deletes a region address by name.
|
||||
func (gce *GCECloud) DeleteRegionAddress(name, region string) error {
|
||||
mc := newAddressMetricContext("delete", region)
|
||||
op, err := gce.service.Addresses.Delete(gce.projectID, region, name).Do()
|
||||
if err != nil {
|
||||
return mc.Observe(err)
|
||||
}
|
||||
return gce.waitForRegionOp(op, region, mc)
|
||||
return mc.Observe(gce.c.Addresses().Delete(context.Background(), meta.RegionalKey(name, region)))
|
||||
}
|
||||
|
||||
// GetRegionAddress returns the region address by name
|
||||
func (gce *GCECloud) GetRegionAddress(name, region string) (*compute.Address, error) {
|
||||
mc := newAddressMetricContext("get", region)
|
||||
v, err := gce.service.Addresses.Get(gce.projectID, region, name).Do()
|
||||
v, err := gce.c.Addresses().Get(context.Background(), meta.RegionalKey(name, region))
|
||||
return v, mc.Observe(err)
|
||||
}
|
||||
|
||||
// GetAlphaRegionAddress returns the Alpha, regional address by name.
|
||||
func (gce *GCECloud) GetAlphaRegionAddress(name, region string) (*computealpha.Address, error) {
|
||||
mc := newAddressMetricContextWithVersion("get", region, computeAlphaVersion)
|
||||
v, err := gce.serviceAlpha.Addresses.Get(gce.projectID, region, name).Do()
|
||||
mc := newAddressMetricContext("get", region)
|
||||
v, err := gce.c.AlphaAddresses().Get(context.Background(), meta.RegionalKey(name, region))
|
||||
return v, mc.Observe(err)
|
||||
}
|
||||
|
||||
// GetBetaRegionAddress returns the beta region address by name
|
||||
func (gce *GCECloud) GetBetaRegionAddress(name, region string) (*computebeta.Address, error) {
|
||||
mc := newAddressMetricContextWithVersion("get", region, computeBetaVersion)
|
||||
v, err := gce.serviceBeta.Addresses.Get(gce.projectID, region, name).Do()
|
||||
mc := newAddressMetricContext("get", region)
|
||||
v, err := gce.c.BetaAddresses().Get(context.Background(), meta.RegionalKey(name, region))
|
||||
return v, mc.Observe(err)
|
||||
}
|
||||
|
||||
// GetRegionAddressByIP returns the regional address matching the given IP address.
|
||||
func (gce *GCECloud) GetRegionAddressByIP(region, ipAddress string) (*compute.Address, error) {
|
||||
mc := newAddressMetricContext("list", region)
|
||||
addrs, err := gce.service.Addresses.List(gce.projectID, region).Filter("address eq " + ipAddress).Do()
|
||||
// Record the metrics for the call.
|
||||
addrs, err := gce.c.Addresses().List(context.Background(), region, filter.Regexp("address", ipAddress))
|
||||
|
||||
mc.Observe(err)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if len(addrs.Items) > 1 {
|
||||
// We don't expect more than one match.
|
||||
addrsToPrint := []compute.Address{}
|
||||
for _, addr := range addrs.Items {
|
||||
addrsToPrint = append(addrsToPrint, *addr)
|
||||
}
|
||||
glog.Errorf("More than one addresses matching the IP %q: %+v", ipAddress, addrsToPrint)
|
||||
if len(addrs) > 1 {
|
||||
glog.Warningf("More than one addresses matching the IP %q: %v", ipAddress, addrNames(addrs))
|
||||
}
|
||||
for _, addr := range addrs.Items {
|
||||
for _, addr := range addrs {
|
||||
if addr.Address == ipAddress {
|
||||
return addr, nil
|
||||
}
|
||||
@ -154,22 +130,17 @@ func (gce *GCECloud) GetRegionAddressByIP(region, ipAddress string) (*compute.Ad
|
||||
// GetBetaRegionAddressByIP returns the beta regional address matching the given IP address.
|
||||
func (gce *GCECloud) GetBetaRegionAddressByIP(region, ipAddress string) (*computebeta.Address, error) {
|
||||
mc := newAddressMetricContext("list", region)
|
||||
addrs, err := gce.serviceBeta.Addresses.List(gce.projectID, region).Filter("address eq " + ipAddress).Do()
|
||||
// Record the metrics for the call.
|
||||
addrs, err := gce.c.BetaAddresses().List(context.Background(), region, filter.Regexp("address", ipAddress))
|
||||
|
||||
mc.Observe(err)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if len(addrs.Items) > 1 {
|
||||
// We don't expect more than one match.
|
||||
addrsToPrint := []computebeta.Address{}
|
||||
for _, addr := range addrs.Items {
|
||||
addrsToPrint = append(addrsToPrint, *addr)
|
||||
}
|
||||
glog.Errorf("More than one addresses matching the IP %q: %+v", ipAddress, addrsToPrint)
|
||||
if len(addrs) > 1 {
|
||||
glog.Warningf("More than one addresses matching the IP %q: %v", ipAddress, addrNames(addrs))
|
||||
}
|
||||
for _, addr := range addrs.Items {
|
||||
for _, addr := range addrs {
|
||||
if addr.Address == ipAddress {
|
||||
return addr, nil
|
||||
}
|
||||
@ -180,7 +151,7 @@ func (gce *GCECloud) GetBetaRegionAddressByIP(region, ipAddress string) (*comput
|
||||
// TODO(#51665): retire this function once Network Tiers becomes Beta in GCP.
|
||||
func (gce *GCECloud) getNetworkTierFromAddress(name, region string) (string, error) {
|
||||
if !gce.AlphaFeatureGate.Enabled(AlphaFeatureNetworkTiers) {
|
||||
return NetworkTierDefault.ToGCEValue(), nil
|
||||
return cloud.NetworkTierDefault.ToGCEValue(), nil
|
||||
}
|
||||
addr, err := gce.GetAlphaRegionAddress(name, region)
|
||||
if err != nil {
|
||||
@ -188,3 +159,18 @@ func (gce *GCECloud) getNetworkTierFromAddress(name, region string) (string, err
|
||||
}
|
||||
return addr.NetworkTier, nil
|
||||
}
|
||||
|
||||
func addrNames(items interface{}) []string {
|
||||
var ret []string
|
||||
switch items := items.(type) {
|
||||
case []compute.Address:
|
||||
for _, a := range items {
|
||||
ret = append(ret, a.Name)
|
||||
}
|
||||
case []computebeta.Address:
|
||||
for _, a := range items {
|
||||
ret = append(ret, a.Name)
|
||||
}
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
12
vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/gce_addresses_fakes.go
generated
vendored
12
vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/gce_addresses_fakes.go
generated
vendored
@ -25,6 +25,8 @@ import (
|
||||
computealpha "google.golang.org/api/compute/v0.alpha"
|
||||
computebeta "google.golang.org/api/compute/v0.beta"
|
||||
compute "google.golang.org/api/compute/v1"
|
||||
|
||||
"k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud"
|
||||
)
|
||||
|
||||
// test
|
||||
@ -49,7 +51,7 @@ func NewFakeCloudAddressService() *FakeCloudAddressService {
|
||||
}
|
||||
}
|
||||
|
||||
// SetRegionalAddresses sets the addresses of ther region. This is used for
|
||||
// SetRegionalAddresses sets the addresses of there region. This is used for
|
||||
// setting the test environment.
|
||||
func (cas *FakeCloudAddressService) SetRegionalAddresses(region string, addrs []*computealpha.Address) {
|
||||
// Reset addresses in the region.
|
||||
@ -68,7 +70,7 @@ func (cas *FakeCloudAddressService) ReserveAlphaRegionAddress(addr *computealpha
|
||||
}
|
||||
|
||||
if addr.AddressType == "" {
|
||||
addr.AddressType = string(schemeExternal)
|
||||
addr.AddressType = string(cloud.SchemeExternal)
|
||||
}
|
||||
|
||||
if cas.reservedAddrs[addr.Address] {
|
||||
@ -76,8 +78,8 @@ func (cas *FakeCloudAddressService) ReserveAlphaRegionAddress(addr *computealpha
|
||||
// When the IP is already in use, this call returns an error code based
|
||||
// on the type (internal vs external) of the address. This is to be
|
||||
// consistent with actual GCE API.
|
||||
switch lbScheme(addr.AddressType) {
|
||||
case schemeExternal:
|
||||
switch cloud.LbScheme(addr.AddressType) {
|
||||
case cloud.SchemeExternal:
|
||||
return makeGoogleAPIError(http.StatusBadRequest, msg)
|
||||
default:
|
||||
return makeGoogleAPIError(http.StatusConflict, msg)
|
||||
@ -209,7 +211,7 @@ func convertToAlphaAddress(object gceObject) *computealpha.Address {
|
||||
panic(fmt.Sprintf("Failed to convert GCE apiObject %v to alpha address: %v", object, err))
|
||||
}
|
||||
// Set the default values for the Alpha fields.
|
||||
addr.NetworkTier = NetworkTierDefault.ToGCEValue()
|
||||
addr.NetworkTier = cloud.NetworkTierDefault.ToGCEValue()
|
||||
return &addr
|
||||
}
|
||||
|
||||
|
3
vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/gce_alpha.go
generated
vendored
3
vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/gce_alpha.go
generated
vendored
@ -29,15 +29,12 @@ const (
|
||||
// tier to use. Currently supports "Standard" and "Premium" (default).
|
||||
AlphaFeatureNetworkTiers = "NetworkTiers"
|
||||
|
||||
AlphaFeatureGCEDisk = "DiskAlphaAPI"
|
||||
|
||||
AlphaFeatureNetworkEndpointGroup = "NetworkEndpointGroup"
|
||||
)
|
||||
|
||||
// All known alpha features
|
||||
var knownAlphaFeatures = map[string]bool{
|
||||
AlphaFeatureNetworkTiers: true,
|
||||
AlphaFeatureGCEDisk: true,
|
||||
AlphaFeatureNetworkEndpointGroup: true,
|
||||
}
|
||||
|
||||
|
42
vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/gce_annotations.go
generated
vendored
42
vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/gce_annotations.go
generated
vendored
@ -18,15 +18,14 @@ package gce
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/golang/glog"
|
||||
|
||||
"k8s.io/api/core/v1"
|
||||
"k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud"
|
||||
)
|
||||
|
||||
type LoadBalancerType string
|
||||
type NetworkTier string
|
||||
|
||||
const (
|
||||
// ServiceAnnotationLoadBalancerType is annotated on a service with type LoadBalancer
|
||||
@ -49,12 +48,8 @@ const (
|
||||
// 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
|
||||
NetworkTierAnnotationStandard = cloud.NetworkTierStandard
|
||||
NetworkTierAnnotationPremium = cloud.NetworkTierPremium
|
||||
)
|
||||
|
||||
// GetLoadBalancerAnnotationType returns the type of GCP load balancer which should be assembled.
|
||||
@ -97,38 +92,19 @@ func GetLoadBalancerAnnotationBackendShare(service *v1.Service) bool {
|
||||
// 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) {
|
||||
func GetServiceNetworkTier(service *v1.Service) (cloud.NetworkTier, error) {
|
||||
l, ok := service.Annotations[NetworkTierAnnotationKey]
|
||||
if !ok {
|
||||
return NetworkTierDefault, nil
|
||||
return cloud.NetworkTierDefault, nil
|
||||
}
|
||||
|
||||
v := NetworkTier(l)
|
||||
v := cloud.NetworkTier(l)
|
||||
switch v {
|
||||
case NetworkTierStandard:
|
||||
case cloud.NetworkTierStandard:
|
||||
fallthrough
|
||||
case NetworkTierPremium:
|
||||
case cloud.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)
|
||||
return cloud.NetworkTierDefault, fmt.Errorf("unsupported network tier: %q", v)
|
||||
}
|
||||
}
|
||||
|
11
vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/gce_annotations_test.go
generated
vendored
11
vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/gce_annotations_test.go
generated
vendored
@ -21,6 +21,7 @@ import (
|
||||
|
||||
"k8s.io/api/core/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
@ -38,24 +39,24 @@ func TestServiceNetworkTierAnnotationKey(t *testing.T) {
|
||||
|
||||
for testName, testCase := range map[string]struct {
|
||||
annotations map[string]string
|
||||
expectedTier NetworkTier
|
||||
expectedTier cloud.NetworkTier
|
||||
expectErr bool
|
||||
}{
|
||||
"Use the default when the annotation does not exist": {
|
||||
annotations: nil,
|
||||
expectedTier: NetworkTierDefault,
|
||||
expectedTier: cloud.NetworkTierDefault,
|
||||
},
|
||||
"Standard tier": {
|
||||
annotations: map[string]string{NetworkTierAnnotationKey: "Standard"},
|
||||
expectedTier: NetworkTierStandard,
|
||||
expectedTier: cloud.NetworkTierStandard,
|
||||
},
|
||||
"Premium tier": {
|
||||
annotations: map[string]string{NetworkTierAnnotationKey: "Premium"},
|
||||
expectedTier: NetworkTierPremium,
|
||||
expectedTier: cloud.NetworkTierPremium,
|
||||
},
|
||||
"Report an error on invalid network tier value": {
|
||||
annotations: map[string]string{NetworkTierAnnotationKey: "Unknown-tier"},
|
||||
expectedTier: NetworkTierPremium,
|
||||
expectedTier: cloud.NetworkTierPremium,
|
||||
expectErr: true,
|
||||
},
|
||||
} {
|
||||
|
114
vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/gce_backendservice.go
generated
vendored
114
vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/gce_backendservice.go
generated
vendored
@ -17,10 +17,13 @@ limitations under the License.
|
||||
package gce
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"context"
|
||||
|
||||
computealpha "google.golang.org/api/compute/v0.alpha"
|
||||
compute "google.golang.org/api/compute/v1"
|
||||
|
||||
"k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud/filter"
|
||||
"k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud/meta"
|
||||
)
|
||||
|
||||
func newBackendServiceMetricContext(request, region string) *metricContext {
|
||||
@ -34,150 +37,105 @@ func newBackendServiceMetricContextWithVersion(request, region, version string)
|
||||
// GetGlobalBackendService retrieves a backend by name.
|
||||
func (gce *GCECloud) GetGlobalBackendService(name string) (*compute.BackendService, error) {
|
||||
mc := newBackendServiceMetricContext("get", "")
|
||||
v, err := gce.service.BackendServices.Get(gce.projectID, name).Do()
|
||||
v, err := gce.c.BackendServices().Get(context.Background(), meta.GlobalKey(name))
|
||||
return v, mc.Observe(err)
|
||||
}
|
||||
|
||||
// GetAlphaGlobalBackendService retrieves alpha backend by name.
|
||||
func (gce *GCECloud) GetAlphaGlobalBackendService(name string) (*computealpha.BackendService, error) {
|
||||
mc := newBackendServiceMetricContextWithVersion("get", "", computeAlphaVersion)
|
||||
v, err := gce.serviceAlpha.BackendServices.Get(gce.projectID, name).Do()
|
||||
v, err := gce.c.AlphaBackendServices().Get(context.Background(), meta.GlobalKey(name))
|
||||
return v, mc.Observe(err)
|
||||
}
|
||||
|
||||
// UpdateGlobalBackendService applies the given BackendService as an update to an existing service.
|
||||
// UpdateGlobalBackendService applies the given BackendService as an update to
|
||||
// an existing service.
|
||||
func (gce *GCECloud) UpdateGlobalBackendService(bg *compute.BackendService) error {
|
||||
mc := newBackendServiceMetricContext("update", "")
|
||||
op, err := gce.service.BackendServices.Update(gce.projectID, bg.Name, bg).Do()
|
||||
if err != nil {
|
||||
return mc.Observe(err)
|
||||
}
|
||||
|
||||
return gce.waitForGlobalOp(op, mc)
|
||||
return mc.Observe(gce.c.BackendServices().Update(context.Background(), meta.GlobalKey(bg.Name), bg))
|
||||
}
|
||||
|
||||
// UpdateAlphaGlobalBackendService applies the given alpha BackendService as an update to an existing service.
|
||||
// UpdateAlphaGlobalBackendService applies the given alpha BackendService as an
|
||||
// update to an existing service.
|
||||
func (gce *GCECloud) UpdateAlphaGlobalBackendService(bg *computealpha.BackendService) error {
|
||||
mc := newBackendServiceMetricContextWithVersion("update", "", computeAlphaVersion)
|
||||
op, err := gce.serviceAlpha.BackendServices.Update(gce.projectID, bg.Name, bg).Do()
|
||||
if err != nil {
|
||||
return mc.Observe(err)
|
||||
}
|
||||
|
||||
return gce.waitForGlobalOp(op, mc)
|
||||
mc := newBackendServiceMetricContext("update", "")
|
||||
return mc.Observe(gce.c.AlphaBackendServices().Update(context.Background(), meta.GlobalKey(bg.Name), bg))
|
||||
}
|
||||
|
||||
// DeleteGlobalBackendService deletes the given BackendService by name.
|
||||
func (gce *GCECloud) DeleteGlobalBackendService(name string) error {
|
||||
mc := newBackendServiceMetricContext("delete", "")
|
||||
op, err := gce.service.BackendServices.Delete(gce.projectID, name).Do()
|
||||
if err != nil {
|
||||
if isHTTPErrorCode(err, http.StatusNotFound) {
|
||||
return nil
|
||||
}
|
||||
return mc.Observe(err)
|
||||
}
|
||||
|
||||
return gce.waitForGlobalOp(op, mc)
|
||||
return mc.Observe(gce.c.BackendServices().Delete(context.Background(), meta.GlobalKey(name)))
|
||||
}
|
||||
|
||||
// CreateGlobalBackendService creates the given BackendService.
|
||||
func (gce *GCECloud) CreateGlobalBackendService(bg *compute.BackendService) error {
|
||||
mc := newBackendServiceMetricContext("create", "")
|
||||
op, err := gce.service.BackendServices.Insert(gce.projectID, bg).Do()
|
||||
if err != nil {
|
||||
return mc.Observe(err)
|
||||
}
|
||||
|
||||
return gce.waitForGlobalOp(op, mc)
|
||||
return mc.Observe(gce.c.BackendServices().Insert(context.Background(), meta.GlobalKey(bg.Name), bg))
|
||||
}
|
||||
|
||||
// CreateAlphaGlobalBackendService creates the given alpha BackendService.
|
||||
func (gce *GCECloud) CreateAlphaGlobalBackendService(bg *computealpha.BackendService) error {
|
||||
mc := newBackendServiceMetricContextWithVersion("create", "", computeAlphaVersion)
|
||||
op, err := gce.serviceAlpha.BackendServices.Insert(gce.projectID, bg).Do()
|
||||
if err != nil {
|
||||
return mc.Observe(err)
|
||||
}
|
||||
|
||||
return gce.waitForGlobalOp(op, mc)
|
||||
mc := newBackendServiceMetricContext("create", "")
|
||||
return mc.Observe(gce.c.AlphaBackendServices().Insert(context.Background(), meta.GlobalKey(bg.Name), bg))
|
||||
}
|
||||
|
||||
// ListGlobalBackendServices lists all backend services in the project.
|
||||
func (gce *GCECloud) ListGlobalBackendServices() (*compute.BackendServiceList, error) {
|
||||
func (gce *GCECloud) ListGlobalBackendServices() ([]*compute.BackendService, error) {
|
||||
mc := newBackendServiceMetricContext("list", "")
|
||||
// TODO: use PageToken to list all not just the first 500
|
||||
v, err := gce.service.BackendServices.List(gce.projectID).Do()
|
||||
v, err := gce.c.BackendServices().List(context.Background(), filter.None)
|
||||
return v, mc.Observe(err)
|
||||
}
|
||||
|
||||
// GetGlobalBackendServiceHealth returns the health of the BackendService identified by the given
|
||||
// name, in the given instanceGroup. The instanceGroupLink is the fully
|
||||
// qualified self link of an instance group.
|
||||
// GetGlobalBackendServiceHealth returns the health of the BackendService
|
||||
// identified by the given name, in the given instanceGroup. The
|
||||
// instanceGroupLink is the fully qualified self link of an instance group.
|
||||
func (gce *GCECloud) GetGlobalBackendServiceHealth(name string, instanceGroupLink string) (*compute.BackendServiceGroupHealth, error) {
|
||||
mc := newBackendServiceMetricContext("get_health", "")
|
||||
groupRef := &compute.ResourceGroupReference{Group: instanceGroupLink}
|
||||
v, err := gce.service.BackendServices.GetHealth(gce.projectID, name, groupRef).Do()
|
||||
v, err := gce.c.BackendServices().GetHealth(context.Background(), meta.GlobalKey(name), groupRef)
|
||||
return v, mc.Observe(err)
|
||||
}
|
||||
|
||||
// GetRegionBackendService retrieves a backend by name.
|
||||
func (gce *GCECloud) GetRegionBackendService(name, region string) (*compute.BackendService, error) {
|
||||
mc := newBackendServiceMetricContext("get", region)
|
||||
v, err := gce.service.RegionBackendServices.Get(gce.projectID, region, name).Do()
|
||||
v, err := gce.c.RegionBackendServices().Get(context.Background(), meta.RegionalKey(name, region))
|
||||
return v, mc.Observe(err)
|
||||
}
|
||||
|
||||
// UpdateRegionBackendService applies the given BackendService as an update to an existing service.
|
||||
// UpdateRegionBackendService applies the given BackendService as an update to
|
||||
// an existing service.
|
||||
func (gce *GCECloud) UpdateRegionBackendService(bg *compute.BackendService, region string) error {
|
||||
mc := newBackendServiceMetricContext("update", region)
|
||||
op, err := gce.service.RegionBackendServices.Update(gce.projectID, region, bg.Name, bg).Do()
|
||||
if err != nil {
|
||||
return mc.Observe(err)
|
||||
}
|
||||
|
||||
return gce.waitForRegionOp(op, region, mc)
|
||||
return mc.Observe(gce.c.RegionBackendServices().Update(context.Background(), meta.RegionalKey(bg.Name, region), bg))
|
||||
}
|
||||
|
||||
// DeleteRegionBackendService deletes the given BackendService by name.
|
||||
func (gce *GCECloud) DeleteRegionBackendService(name, region string) error {
|
||||
mc := newBackendServiceMetricContext("delete", region)
|
||||
op, err := gce.service.RegionBackendServices.Delete(gce.projectID, region, name).Do()
|
||||
if err != nil {
|
||||
if isHTTPErrorCode(err, http.StatusNotFound) {
|
||||
return nil
|
||||
}
|
||||
return mc.Observe(err)
|
||||
}
|
||||
|
||||
return gce.waitForRegionOp(op, region, mc)
|
||||
return mc.Observe(gce.c.RegionBackendServices().Delete(context.Background(), meta.RegionalKey(name, region)))
|
||||
}
|
||||
|
||||
// CreateRegionBackendService creates the given BackendService.
|
||||
func (gce *GCECloud) CreateRegionBackendService(bg *compute.BackendService, region string) error {
|
||||
mc := newBackendServiceMetricContext("create", region)
|
||||
op, err := gce.service.RegionBackendServices.Insert(gce.projectID, region, bg).Do()
|
||||
if err != nil {
|
||||
return mc.Observe(err)
|
||||
}
|
||||
|
||||
return gce.waitForRegionOp(op, region, mc)
|
||||
return mc.Observe(gce.c.RegionBackendServices().Insert(context.Background(), meta.RegionalKey(bg.Name, region), bg))
|
||||
}
|
||||
|
||||
// ListRegionBackendServices lists all backend services in the project.
|
||||
func (gce *GCECloud) ListRegionBackendServices(region string) (*compute.BackendServiceList, error) {
|
||||
func (gce *GCECloud) ListRegionBackendServices(region string) ([]*compute.BackendService, error) {
|
||||
mc := newBackendServiceMetricContext("list", region)
|
||||
// TODO: use PageToken to list all not just the first 500
|
||||
v, err := gce.service.RegionBackendServices.List(gce.projectID, region).Do()
|
||||
v, err := gce.c.RegionBackendServices().List(context.Background(), region, filter.None)
|
||||
return v, mc.Observe(err)
|
||||
}
|
||||
|
||||
// GetRegionalBackendServiceHealth returns the health of the BackendService identified by the given
|
||||
// name, in the given instanceGroup. The instanceGroupLink is the fully
|
||||
// qualified self link of an instance group.
|
||||
// GetRegionalBackendServiceHealth returns the health of the BackendService
|
||||
// identified by the given name, in the given instanceGroup. The
|
||||
// instanceGroupLink is the fully qualified self link of an instance group.
|
||||
func (gce *GCECloud) GetRegionalBackendServiceHealth(name, region string, instanceGroupLink string) (*compute.BackendServiceGroupHealth, error) {
|
||||
mc := newBackendServiceMetricContext("get_health", region)
|
||||
groupRef := &compute.ResourceGroupReference{Group: instanceGroupLink}
|
||||
v, err := gce.service.RegionBackendServices.GetHealth(gce.projectID, region, name, groupRef).Do()
|
||||
ref := &compute.ResourceGroupReference{Group: instanceGroupLink}
|
||||
v, err := gce.c.RegionBackendServices().GetHealth(context.Background(), meta.RegionalKey(name, region), ref)
|
||||
return v, mc.Observe(err)
|
||||
}
|
||||
|
32
vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/gce_cert.go
generated
vendored
32
vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/gce_cert.go
generated
vendored
@ -17,9 +17,12 @@ limitations under the License.
|
||||
package gce
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"context"
|
||||
|
||||
compute "google.golang.org/api/compute/v1"
|
||||
|
||||
"k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud/filter"
|
||||
"k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud/meta"
|
||||
)
|
||||
|
||||
func newCertMetricContext(request string) *metricContext {
|
||||
@ -29,46 +32,29 @@ func newCertMetricContext(request string) *metricContext {
|
||||
// GetSslCertificate returns the SslCertificate by name.
|
||||
func (gce *GCECloud) GetSslCertificate(name string) (*compute.SslCertificate, error) {
|
||||
mc := newCertMetricContext("get")
|
||||
v, err := gce.service.SslCertificates.Get(gce.projectID, name).Do()
|
||||
v, err := gce.c.SslCertificates().Get(context.Background(), meta.GlobalKey(name))
|
||||
return v, mc.Observe(err)
|
||||
}
|
||||
|
||||
// CreateSslCertificate creates and returns a SslCertificate.
|
||||
func (gce *GCECloud) CreateSslCertificate(sslCerts *compute.SslCertificate) (*compute.SslCertificate, error) {
|
||||
mc := newCertMetricContext("create")
|
||||
op, err := gce.service.SslCertificates.Insert(gce.projectID, sslCerts).Do()
|
||||
|
||||
err := gce.c.SslCertificates().Insert(context.Background(), meta.GlobalKey(sslCerts.Name), sslCerts)
|
||||
if err != nil {
|
||||
return nil, mc.Observe(err)
|
||||
}
|
||||
|
||||
if err = gce.waitForGlobalOp(op, mc); err != nil {
|
||||
return nil, mc.Observe(err)
|
||||
}
|
||||
|
||||
return gce.GetSslCertificate(sslCerts.Name)
|
||||
}
|
||||
|
||||
// DeleteSslCertificate deletes the SslCertificate by name.
|
||||
func (gce *GCECloud) DeleteSslCertificate(name string) error {
|
||||
mc := newCertMetricContext("delete")
|
||||
op, err := gce.service.SslCertificates.Delete(gce.projectID, name).Do()
|
||||
|
||||
if err != nil {
|
||||
if isHTTPErrorCode(err, http.StatusNotFound) {
|
||||
return nil
|
||||
}
|
||||
|
||||
return mc.Observe(err)
|
||||
}
|
||||
|
||||
return gce.waitForGlobalOp(op, mc)
|
||||
return mc.Observe(gce.c.SslCertificates().Delete(context.Background(), meta.GlobalKey(name)))
|
||||
}
|
||||
|
||||
// ListSslCertificates lists all SslCertificates in the project.
|
||||
func (gce *GCECloud) ListSslCertificates() (*compute.SslCertificateList, error) {
|
||||
func (gce *GCECloud) ListSslCertificates() ([]*compute.SslCertificate, error) {
|
||||
mc := newCertMetricContext("list")
|
||||
// TODO: use PageToken to list all not just the first 500
|
||||
v, err := gce.service.SslCertificates.List(gce.projectID).Do()
|
||||
v, err := gce.c.SslCertificates().List(context.Background(), filter.None)
|
||||
return v, mc.Observe(err)
|
||||
}
|
||||
|
6
vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/gce_clusters.go
generated
vendored
6
vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/gce_clusters.go
generated
vendored
@ -16,11 +16,13 @@ limitations under the License.
|
||||
|
||||
package gce
|
||||
|
||||
import "context"
|
||||
|
||||
func newClustersMetricContext(request, zone string) *metricContext {
|
||||
return newGenericMetricContext("clusters", request, unusedMetricLabel, zone, computeV1Version)
|
||||
}
|
||||
|
||||
func (gce *GCECloud) ListClusters() ([]string, error) {
|
||||
func (gce *GCECloud) ListClusters(ctx context.Context) ([]string, error) {
|
||||
allClusters := []string{}
|
||||
|
||||
for _, zone := range gce.managedZones {
|
||||
@ -35,7 +37,7 @@ func (gce *GCECloud) ListClusters() ([]string, error) {
|
||||
return allClusters, nil
|
||||
}
|
||||
|
||||
func (gce *GCECloud) Master(clusterName string) (string, error) {
|
||||
func (gce *GCECloud) Master(ctx context.Context, clusterName string) (string, error) {
|
||||
return "k8s-" + clusterName + "-master.internal", nil
|
||||
}
|
||||
|
||||
|
223
vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/gce_disks.go
generated
vendored
223
vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/gce_disks.go
generated
vendored
@ -17,6 +17,7 @@ limitations under the License.
|
||||
package gce
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/http"
|
||||
@ -36,6 +37,8 @@ import (
|
||||
computealpha "google.golang.org/api/compute/v0.alpha"
|
||||
compute "google.golang.org/api/compute/v1"
|
||||
"google.golang.org/api/googleapi"
|
||||
utilfeature "k8s.io/apiserver/pkg/util/feature"
|
||||
"k8s.io/kubernetes/pkg/features"
|
||||
)
|
||||
|
||||
type DiskType string
|
||||
@ -111,6 +114,8 @@ type gceServiceManager struct {
|
||||
gce *GCECloud
|
||||
}
|
||||
|
||||
var _ diskServiceManager = &gceServiceManager{}
|
||||
|
||||
func (manager *gceServiceManager) CreateDiskOnCloudProvider(
|
||||
name string,
|
||||
sizeGb int64,
|
||||
@ -118,23 +123,11 @@ func (manager *gceServiceManager) CreateDiskOnCloudProvider(
|
||||
diskType string,
|
||||
zone string) (gceObject, error) {
|
||||
diskTypeURI, err := manager.getDiskTypeURI(
|
||||
manager.gce.region /* diskRegion */, singleZone{zone}, diskType)
|
||||
manager.gce.region /* diskRegion */, singleZone{zone}, diskType, false /* useAlphaAPI */)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if manager.gce.AlphaFeatureGate.Enabled(AlphaFeatureGCEDisk) {
|
||||
diskToCreateAlpha := &computealpha.Disk{
|
||||
Name: name,
|
||||
SizeGb: sizeGb,
|
||||
Description: tagsStr,
|
||||
Type: diskTypeURI,
|
||||
}
|
||||
|
||||
return manager.gce.serviceAlpha.Disks.Insert(
|
||||
manager.gce.projectID, zone, diskToCreateAlpha).Do()
|
||||
}
|
||||
|
||||
diskToCreateV1 := &compute.Disk{
|
||||
Name: name,
|
||||
SizeGb: sizeGb,
|
||||
@ -151,17 +144,19 @@ func (manager *gceServiceManager) CreateRegionalDiskOnCloudProvider(
|
||||
tagsStr string,
|
||||
diskType string,
|
||||
replicaZones sets.String) (gceObject, error) {
|
||||
diskTypeURI, err := manager.getDiskTypeURI(
|
||||
manager.gce.region /* diskRegion */, multiZone{replicaZones}, diskType)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
fullyQualifiedReplicaZones := []string{}
|
||||
for _, replicaZone := range replicaZones.UnsortedList() {
|
||||
fullyQualifiedReplicaZones = append(
|
||||
fullyQualifiedReplicaZones, manager.getReplicaZoneURI(replicaZone))
|
||||
}
|
||||
if manager.gce.AlphaFeatureGate.Enabled(AlphaFeatureGCEDisk) {
|
||||
|
||||
if utilfeature.DefaultFeatureGate.Enabled(features.GCERegionalPersistentDisk) {
|
||||
diskTypeURI, err := manager.getDiskTypeURI(
|
||||
manager.gce.region /* diskRegion */, multiZone{replicaZones}, diskType, true /* useAlphaAPI */)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
fullyQualifiedReplicaZones := []string{}
|
||||
for _, replicaZone := range replicaZones.UnsortedList() {
|
||||
fullyQualifiedReplicaZones = append(
|
||||
fullyQualifiedReplicaZones, manager.getReplicaZoneURI(replicaZone, true))
|
||||
}
|
||||
|
||||
diskToCreateAlpha := &computealpha.Disk{
|
||||
Name: name,
|
||||
SizeGb: sizeGb,
|
||||
@ -173,7 +168,7 @@ func (manager *gceServiceManager) CreateRegionalDiskOnCloudProvider(
|
||||
manager.gce.projectID, manager.gce.region, diskToCreateAlpha).Do()
|
||||
}
|
||||
|
||||
return nil, fmt.Errorf("The regional PD feature is only available via the GCE Alpha API. Enable \"GCEDiskAlphaAPI\" in the list of \"alpha-features\" in \"gce.conf\" to use the feature.")
|
||||
return nil, fmt.Errorf("the regional PD feature is only available with the %s Kubernetes feature gate enabled", features.GCERegionalPersistentDisk)
|
||||
}
|
||||
|
||||
func (manager *gceServiceManager) AttachDiskOnCloudProvider(
|
||||
@ -186,24 +181,12 @@ func (manager *gceServiceManager) AttachDiskOnCloudProvider(
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if manager.gce.AlphaFeatureGate.Enabled(AlphaFeatureGCEDisk) {
|
||||
attachedDiskAlpha := &computealpha.AttachedDisk{
|
||||
DeviceName: disk.Name,
|
||||
Kind: disk.Kind,
|
||||
Mode: readWrite,
|
||||
Source: source,
|
||||
Type: diskTypePersistent,
|
||||
}
|
||||
return manager.gce.serviceAlpha.Instances.AttachDisk(
|
||||
manager.gce.projectID, instanceZone, instanceName, attachedDiskAlpha).Do()
|
||||
}
|
||||
|
||||
attachedDiskV1 := &compute.AttachedDisk{
|
||||
DeviceName: disk.Name,
|
||||
Kind: disk.Kind,
|
||||
Mode: readWrite,
|
||||
Source: source,
|
||||
Type: disk.Type,
|
||||
Type: diskTypePersistent,
|
||||
}
|
||||
return manager.gce.service.Instances.AttachDisk(
|
||||
manager.gce.projectID, instanceZone, instanceName, attachedDiskV1).Do()
|
||||
@ -213,11 +196,6 @@ func (manager *gceServiceManager) DetachDiskOnCloudProvider(
|
||||
instanceZone string,
|
||||
instanceName string,
|
||||
devicePath string) (gceObject, error) {
|
||||
if manager.gce.AlphaFeatureGate.Enabled(AlphaFeatureGCEDisk) {
|
||||
manager.gce.serviceAlpha.Instances.DetachDisk(
|
||||
manager.gce.projectID, instanceZone, instanceName, devicePath).Do()
|
||||
}
|
||||
|
||||
return manager.gce.service.Instances.DetachDisk(
|
||||
manager.gce.projectID, instanceZone, instanceName, devicePath).Do()
|
||||
}
|
||||
@ -233,45 +211,6 @@ func (manager *gceServiceManager) GetDiskFromCloudProvider(
|
||||
return nil, fmt.Errorf("Can not fetch disk. Zone is specified (%q). But disk name is empty.", zone)
|
||||
}
|
||||
|
||||
if manager.gce.AlphaFeatureGate.Enabled(AlphaFeatureGCEDisk) {
|
||||
diskAlpha, err := manager.gce.serviceAlpha.Disks.Get(
|
||||
manager.gce.projectID, zone, diskName).Do()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var zoneInfo zoneType
|
||||
if len(diskAlpha.ReplicaZones) > 1 {
|
||||
zones := sets.NewString()
|
||||
for _, zoneURI := range diskAlpha.ReplicaZones {
|
||||
zones.Insert(lastComponent(zoneURI))
|
||||
}
|
||||
zoneInfo = multiZone{zones}
|
||||
} else {
|
||||
zoneInfo = singleZone{lastComponent(diskAlpha.Zone)}
|
||||
if diskAlpha.Zone == "" {
|
||||
zoneInfo = singleZone{lastComponent(zone)}
|
||||
}
|
||||
}
|
||||
|
||||
region := strings.TrimSpace(lastComponent(diskAlpha.Region))
|
||||
if region == "" {
|
||||
region, err = manager.getRegionFromZone(zoneInfo)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to extract region from zone for %q/%q err=%v", zone, diskName, err)
|
||||
}
|
||||
}
|
||||
|
||||
return &GCEDisk{
|
||||
ZoneInfo: zoneInfo,
|
||||
Region: region,
|
||||
Name: diskAlpha.Name,
|
||||
Kind: diskAlpha.Kind,
|
||||
Type: diskAlpha.Type,
|
||||
SizeGb: diskAlpha.SizeGb,
|
||||
}, nil
|
||||
}
|
||||
|
||||
diskStable, err := manager.gce.service.Disks.Get(
|
||||
manager.gce.projectID, zone, diskName).Do()
|
||||
if err != nil {
|
||||
@ -301,7 +240,7 @@ func (manager *gceServiceManager) GetDiskFromCloudProvider(
|
||||
func (manager *gceServiceManager) GetRegionalDiskFromCloudProvider(
|
||||
diskName string) (*GCEDisk, error) {
|
||||
|
||||
if manager.gce.AlphaFeatureGate.Enabled(AlphaFeatureGCEDisk) {
|
||||
if utilfeature.DefaultFeatureGate.Enabled(features.GCERegionalPersistentDisk) {
|
||||
diskAlpha, err := manager.gce.serviceAlpha.RegionDisks.Get(
|
||||
manager.gce.projectID, manager.gce.region, diskName).Do()
|
||||
if err != nil {
|
||||
@ -323,30 +262,24 @@ func (manager *gceServiceManager) GetRegionalDiskFromCloudProvider(
|
||||
}, nil
|
||||
}
|
||||
|
||||
return nil, fmt.Errorf("The regional PD feature is only available via the GCE Alpha API. Enable \"GCEDiskAlphaAPI\" in the list of \"alpha-features\" in \"gce.conf\" to use the feature.")
|
||||
return nil, fmt.Errorf("the regional PD feature is only available with the %s Kubernetes feature gate enabled", features.GCERegionalPersistentDisk)
|
||||
}
|
||||
|
||||
func (manager *gceServiceManager) DeleteDiskOnCloudProvider(
|
||||
zone string,
|
||||
diskName string) (gceObject, error) {
|
||||
|
||||
if manager.gce.AlphaFeatureGate.Enabled(AlphaFeatureGCEDisk) {
|
||||
return manager.gce.serviceAlpha.Disks.Delete(
|
||||
manager.gce.projectID, zone, diskName).Do()
|
||||
}
|
||||
|
||||
return manager.gce.service.Disks.Delete(
|
||||
manager.gce.projectID, zone, diskName).Do()
|
||||
}
|
||||
|
||||
func (manager *gceServiceManager) DeleteRegionalDiskOnCloudProvider(
|
||||
diskName string) (gceObject, error) {
|
||||
if manager.gce.AlphaFeatureGate.Enabled(AlphaFeatureGCEDisk) {
|
||||
if utilfeature.DefaultFeatureGate.Enabled(features.GCERegionalPersistentDisk) {
|
||||
return manager.gce.serviceAlpha.RegionDisks.Delete(
|
||||
manager.gce.projectID, manager.gce.region, diskName).Do()
|
||||
}
|
||||
|
||||
return nil, fmt.Errorf("DeleteRegionalDiskOnCloudProvider is a regional PD feature and is only available via the GCE Alpha API. Enable \"GCEDiskAlphaAPI\" in the list of \"alpha-features\" in \"gce.conf\" to use the feature.")
|
||||
return nil, fmt.Errorf("the regional PD feature is only available with the %s Kubernetes feature gate enabled", features.GCERegionalPersistentDisk)
|
||||
}
|
||||
|
||||
func (manager *gceServiceManager) WaitForZoneOp(
|
||||
@ -361,9 +294,6 @@ func (manager *gceServiceManager) WaitForRegionalOp(
|
||||
|
||||
func (manager *gceServiceManager) getDiskSourceURI(disk *GCEDisk) (string, error) {
|
||||
getProjectsAPIEndpoint := manager.getProjectsAPIEndpoint()
|
||||
if manager.gce.AlphaFeatureGate.Enabled(AlphaFeatureGCEDisk) {
|
||||
getProjectsAPIEndpoint = manager.getProjectsAPIEndpointAlpha()
|
||||
}
|
||||
|
||||
switch zoneInfo := disk.ZoneInfo.(type) {
|
||||
case singleZone:
|
||||
@ -397,10 +327,13 @@ func (manager *gceServiceManager) getDiskSourceURI(disk *GCEDisk) (string, error
|
||||
}
|
||||
|
||||
func (manager *gceServiceManager) getDiskTypeURI(
|
||||
diskRegion string, diskZoneInfo zoneType, diskType string) (string, error) {
|
||||
getProjectsAPIEndpoint := manager.getProjectsAPIEndpoint()
|
||||
if manager.gce.AlphaFeatureGate.Enabled(AlphaFeatureGCEDisk) {
|
||||
diskRegion string, diskZoneInfo zoneType, diskType string, useAlphaAPI bool) (string, error) {
|
||||
|
||||
var getProjectsAPIEndpoint string
|
||||
if useAlphaAPI {
|
||||
getProjectsAPIEndpoint = manager.getProjectsAPIEndpointAlpha()
|
||||
} else {
|
||||
getProjectsAPIEndpoint = manager.getProjectsAPIEndpoint()
|
||||
}
|
||||
|
||||
switch zoneInfo := diskZoneInfo.(type) {
|
||||
@ -430,10 +363,12 @@ func (manager *gceServiceManager) getDiskTypeURI(
|
||||
}
|
||||
}
|
||||
|
||||
func (manager *gceServiceManager) getReplicaZoneURI(zone string) string {
|
||||
getProjectsAPIEndpoint := manager.getProjectsAPIEndpoint()
|
||||
if manager.gce.AlphaFeatureGate.Enabled(AlphaFeatureGCEDisk) {
|
||||
func (manager *gceServiceManager) getReplicaZoneURI(zone string, useAlphaAPI bool) string {
|
||||
var getProjectsAPIEndpoint string
|
||||
if useAlphaAPI {
|
||||
getProjectsAPIEndpoint = manager.getProjectsAPIEndpointAlpha()
|
||||
} else {
|
||||
getProjectsAPIEndpoint = manager.getProjectsAPIEndpoint()
|
||||
}
|
||||
|
||||
return getProjectsAPIEndpoint + fmt.Sprintf(
|
||||
@ -477,13 +412,6 @@ func (manager *gceServiceManager) getRegionFromZone(zoneInfo zoneType) (string,
|
||||
}
|
||||
|
||||
func (manager *gceServiceManager) ResizeDiskOnCloudProvider(disk *GCEDisk, sizeGb int64, zone string) (gceObject, error) {
|
||||
if manager.gce.AlphaFeatureGate.Enabled(AlphaFeatureGCEDisk) {
|
||||
resizeServiceRequest := &computealpha.DisksResizeRequest{
|
||||
SizeGb: sizeGb,
|
||||
}
|
||||
return manager.gce.serviceAlpha.Disks.Resize(manager.gce.projectID, zone, disk.Name, resizeServiceRequest).Do()
|
||||
|
||||
}
|
||||
resizeServiceRequest := &compute.DisksResizeRequest{
|
||||
SizeGb: sizeGb,
|
||||
}
|
||||
@ -491,20 +419,20 @@ func (manager *gceServiceManager) ResizeDiskOnCloudProvider(disk *GCEDisk, sizeG
|
||||
}
|
||||
|
||||
func (manager *gceServiceManager) RegionalResizeDiskOnCloudProvider(disk *GCEDisk, sizeGb int64) (gceObject, error) {
|
||||
if manager.gce.AlphaFeatureGate.Enabled(AlphaFeatureGCEDisk) {
|
||||
if utilfeature.DefaultFeatureGate.Enabled(features.GCERegionalPersistentDisk) {
|
||||
resizeServiceRequest := &computealpha.RegionDisksResizeRequest{
|
||||
SizeGb: sizeGb,
|
||||
}
|
||||
return manager.gce.serviceAlpha.RegionDisks.Resize(manager.gce.projectID, disk.Region, disk.Name, resizeServiceRequest).Do()
|
||||
}
|
||||
return nil, fmt.Errorf("RegionalResizeDiskOnCloudProvider is a regional PD feature and is only available via the GCE Alpha API. Enable \"GCEDiskAlphaAPI\" in the list of \"alpha-features\" in \"gce.conf\" to use the feature.")
|
||||
return nil, fmt.Errorf("the regional PD feature is only available with the %s Kubernetes feature gate enabled", features.GCERegionalPersistentDisk)
|
||||
}
|
||||
|
||||
// Disks is interface for manipulation with GCE PDs.
|
||||
type Disks interface {
|
||||
// AttachDisk attaches given disk to the node with the specified NodeName.
|
||||
// Current instance is used when instanceID is empty string.
|
||||
AttachDisk(diskName string, nodeName types.NodeName, readOnly bool) error
|
||||
AttachDisk(diskName string, nodeName types.NodeName, readOnly bool, regional bool) error
|
||||
|
||||
// DetachDisk detaches given disk to the node with the specified NodeName.
|
||||
// Current instance is used when nodeName is empty string.
|
||||
@ -577,7 +505,7 @@ func newDiskMetricContextRegional(request, region string) *metricContext {
|
||||
return newGenericMetricContext("disk", request, region, unusedMetricLabel, computeV1Version)
|
||||
}
|
||||
|
||||
func (gce *GCECloud) GetLabelsForVolume(pv *v1.PersistentVolume) (map[string]string, error) {
|
||||
func (gce *GCECloud) GetLabelsForVolume(ctx context.Context, pv *v1.PersistentVolume) (map[string]string, error) {
|
||||
// Ignore any volumes that are being provisioned
|
||||
if pv.Spec.GCEPersistentDisk.PDName == volume.ProvisionedVolumeName {
|
||||
return nil, nil
|
||||
@ -594,7 +522,7 @@ func (gce *GCECloud) GetLabelsForVolume(pv *v1.PersistentVolume) (map[string]str
|
||||
return labels, nil
|
||||
}
|
||||
|
||||
func (gce *GCECloud) AttachDisk(diskName string, nodeName types.NodeName, readOnly bool) error {
|
||||
func (gce *GCECloud) AttachDisk(diskName string, nodeName types.NodeName, readOnly bool, regional bool) error {
|
||||
instanceName := mapNodeNameToInstanceName(nodeName)
|
||||
instance, err := gce.getInstanceByName(instanceName)
|
||||
if err != nil {
|
||||
@ -604,7 +532,7 @@ func (gce *GCECloud) AttachDisk(diskName string, nodeName types.NodeName, readOn
|
||||
// Try fetching as regional PD
|
||||
var disk *GCEDisk
|
||||
var mc *metricContext
|
||||
if gce.AlphaFeatureGate.Enabled(AlphaFeatureGCEDisk) {
|
||||
if regional && utilfeature.DefaultFeatureGate.Enabled(features.GCERegionalPersistentDisk) {
|
||||
disk, err = gce.getRegionalDiskByName(diskName)
|
||||
if err != nil {
|
||||
glog.V(5).Infof("Could not find regional PD named %q to Attach. Will look for a zonal PD", diskName)
|
||||
@ -845,7 +773,7 @@ func (gce *GCECloud) ResizeDisk(diskToResize string, oldSize resource.Quantity,
|
||||
|
||||
requestBytes := newSize.Value()
|
||||
// GCE resizes in chunks of GBs (not GiB)
|
||||
requestGB := volume.RoundUpSize(requestBytes, 1000*1000*1000)
|
||||
requestGB := volumeutil.RoundUpSize(requestBytes, 1000*1000*1000)
|
||||
newSizeQuant := resource.MustParse(fmt.Sprintf("%dG", requestGB))
|
||||
|
||||
// If disk is already of size equal or greater than requested size, we simply return
|
||||
@ -869,17 +797,20 @@ func (gce *GCECloud) ResizeDisk(diskToResize string, oldSize resource.Quantity,
|
||||
}
|
||||
return newSizeQuant, nil
|
||||
case multiZone:
|
||||
mc = newDiskMetricContextRegional("resize", disk.Region)
|
||||
resizeOp, err := gce.manager.RegionalResizeDiskOnCloudProvider(disk, requestGB)
|
||||
if utilfeature.DefaultFeatureGate.Enabled(features.GCERegionalPersistentDisk) {
|
||||
mc = newDiskMetricContextRegional("resize", disk.Region)
|
||||
resizeOp, err := gce.manager.RegionalResizeDiskOnCloudProvider(disk, requestGB)
|
||||
|
||||
if err != nil {
|
||||
return oldSize, mc.Observe(err)
|
||||
if err != nil {
|
||||
return oldSize, mc.Observe(err)
|
||||
}
|
||||
waitErr := gce.manager.WaitForRegionalOp(resizeOp, mc)
|
||||
if waitErr != nil {
|
||||
return oldSize, waitErr
|
||||
}
|
||||
return newSizeQuant, nil
|
||||
}
|
||||
waitErr := gce.manager.WaitForRegionalOp(resizeOp, mc)
|
||||
if waitErr != nil {
|
||||
return oldSize, waitErr
|
||||
}
|
||||
return newSizeQuant, nil
|
||||
return oldSize, fmt.Errorf("disk.ZoneInfo has unexpected type %T", zoneInfo)
|
||||
case nil:
|
||||
return oldSize, fmt.Errorf("PD has nil ZoneInfo: %v", disk)
|
||||
default:
|
||||
@ -912,19 +843,26 @@ func (gce *GCECloud) GetAutoLabelsForPD(name string, zone string) (map[string]st
|
||||
// We could assume the disks exists; we have all the information we need
|
||||
// However it is more consistent to ensure the disk exists,
|
||||
// and in future we may gather addition information (e.g. disk type, IOPS etc)
|
||||
zoneSet, err := volumeutil.LabelZonesToSet(zone)
|
||||
if err != nil {
|
||||
glog.Warningf("Failed to parse zone field: %q. Will use raw field.", zone)
|
||||
}
|
||||
|
||||
if len(zoneSet) > 1 {
|
||||
// Regional PD
|
||||
disk, err = gce.getRegionalDiskByName(name)
|
||||
if utilfeature.DefaultFeatureGate.Enabled(features.GCERegionalPersistentDisk) {
|
||||
zoneSet, err := volumeutil.LabelZonesToSet(zone)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
glog.Warningf("Failed to parse zone field: %q. Will use raw field.", zone)
|
||||
}
|
||||
|
||||
if len(zoneSet) > 1 {
|
||||
// Regional PD
|
||||
disk, err = gce.getRegionalDiskByName(name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
} else {
|
||||
// Zonal PD
|
||||
disk, err = gce.getDiskByName(name, zone)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Zonal PD
|
||||
disk, err = gce.getDiskByName(name, zone)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@ -1010,7 +948,7 @@ func (gce *GCECloud) getRegionalDiskByName(diskName string) (*GCEDisk, error) {
|
||||
// Prefer getDiskByName, if the zone can be established
|
||||
// Return cloudprovider.DiskNotFound if the given disk cannot be found in any zone
|
||||
func (gce *GCECloud) GetDiskByNameUnknownZone(diskName string) (*GCEDisk, error) {
|
||||
if gce.AlphaFeatureGate.Enabled(AlphaFeatureGCEDisk) {
|
||||
if utilfeature.DefaultFeatureGate.Enabled(features.GCERegionalPersistentDisk) {
|
||||
regionalDisk, err := gce.getRegionalDiskByName(diskName)
|
||||
if err == nil {
|
||||
return regionalDisk, err
|
||||
@ -1020,7 +958,7 @@ func (gce *GCECloud) GetDiskByNameUnknownZone(diskName string) (*GCEDisk, error)
|
||||
// Note: this is the gotcha right now with GCE PD support:
|
||||
// disk names are not unique per-region.
|
||||
// (I can create two volumes with name "myvol" in e.g. us-central1-b & us-central1-f)
|
||||
// For now, this is simply undefined behvaiour.
|
||||
// For now, this is simply undefined behaviour.
|
||||
//
|
||||
// In future, we will have to require users to qualify their disk
|
||||
// "us-central1-a/mydisk". We could do this for them as part of
|
||||
@ -1094,12 +1032,15 @@ func (gce *GCECloud) doDeleteDisk(diskToDelete string) error {
|
||||
}
|
||||
return gce.manager.WaitForZoneOp(deleteOp, zoneInfo.zone, mc)
|
||||
case multiZone:
|
||||
mc = newDiskMetricContextRegional("delete", disk.Region)
|
||||
deleteOp, err := gce.manager.DeleteRegionalDiskOnCloudProvider(disk.Name)
|
||||
if err != nil {
|
||||
return mc.Observe(err)
|
||||
if utilfeature.DefaultFeatureGate.Enabled(features.GCERegionalPersistentDisk) {
|
||||
mc = newDiskMetricContextRegional("delete", disk.Region)
|
||||
deleteOp, err := gce.manager.DeleteRegionalDiskOnCloudProvider(disk.Name)
|
||||
if err != nil {
|
||||
return mc.Observe(err)
|
||||
}
|
||||
return gce.manager.WaitForRegionalOp(deleteOp, mc)
|
||||
}
|
||||
return gce.manager.WaitForRegionalOp(deleteOp, mc)
|
||||
return fmt.Errorf("disk.ZoneInfo has unexpected type %T", zoneInfo)
|
||||
case nil:
|
||||
return fmt.Errorf("PD has nil ZoneInfo: %v", disk)
|
||||
default:
|
||||
|
5
vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/gce_disks_test.go
generated
vendored
5
vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/gce_disks_test.go
generated
vendored
@ -100,16 +100,11 @@ func TestCreateRegionalDisk_Basic(t *testing.T) {
|
||||
gceRegion := "fake-region"
|
||||
zonesWithNodes := []string{"zone1", "zone3", "zone2"}
|
||||
fakeManager := newFakeManager(gceProjectId, gceRegion)
|
||||
alphaFeatureGate, featureGateErr := NewAlphaFeatureGate([]string{AlphaFeatureGCEDisk})
|
||||
|
||||
if featureGateErr != nil {
|
||||
t.Error(featureGateErr)
|
||||
}
|
||||
gce := GCECloud{
|
||||
manager: fakeManager,
|
||||
managedZones: zonesWithNodes,
|
||||
projectID: gceProjectId,
|
||||
AlphaFeatureGate: alphaFeatureGate,
|
||||
nodeZones: createNodeZones(zonesWithNodes),
|
||||
nodeInformerSynced: func() bool { return true },
|
||||
}
|
||||
|
26
vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/gce_firewall.go
generated
vendored
26
vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/gce_firewall.go
generated
vendored
@ -17,7 +17,11 @@ limitations under the License.
|
||||
package gce
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
compute "google.golang.org/api/compute/v1"
|
||||
|
||||
"k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud/meta"
|
||||
)
|
||||
|
||||
func newFirewallMetricContext(request string) *metricContext {
|
||||
@ -27,38 +31,24 @@ func newFirewallMetricContext(request string) *metricContext {
|
||||
// GetFirewall returns the Firewall by name.
|
||||
func (gce *GCECloud) GetFirewall(name string) (*compute.Firewall, error) {
|
||||
mc := newFirewallMetricContext("get")
|
||||
v, err := gce.service.Firewalls.Get(gce.NetworkProjectID(), name).Do()
|
||||
v, err := gce.c.Firewalls().Get(context.Background(), meta.GlobalKey(name))
|
||||
return v, mc.Observe(err)
|
||||
}
|
||||
|
||||
// CreateFirewall creates the passed firewall
|
||||
func (gce *GCECloud) CreateFirewall(f *compute.Firewall) error {
|
||||
mc := newFirewallMetricContext("create")
|
||||
op, err := gce.service.Firewalls.Insert(gce.NetworkProjectID(), f).Do()
|
||||
if err != nil {
|
||||
return mc.Observe(err)
|
||||
}
|
||||
|
||||
return gce.waitForGlobalOpInProject(op, gce.NetworkProjectID(), mc)
|
||||
return mc.Observe(gce.c.Firewalls().Insert(context.Background(), meta.GlobalKey(f.Name), f))
|
||||
}
|
||||
|
||||
// DeleteFirewall deletes the given firewall rule.
|
||||
func (gce *GCECloud) DeleteFirewall(name string) error {
|
||||
mc := newFirewallMetricContext("delete")
|
||||
op, err := gce.service.Firewalls.Delete(gce.NetworkProjectID(), name).Do()
|
||||
if err != nil {
|
||||
return mc.Observe(err)
|
||||
}
|
||||
return gce.waitForGlobalOpInProject(op, gce.NetworkProjectID(), mc)
|
||||
return mc.Observe(gce.c.Firewalls().Delete(context.Background(), meta.GlobalKey(name)))
|
||||
}
|
||||
|
||||
// UpdateFirewall applies the given firewall as an update to an existing service.
|
||||
func (gce *GCECloud) UpdateFirewall(f *compute.Firewall) error {
|
||||
mc := newFirewallMetricContext("update")
|
||||
op, err := gce.service.Firewalls.Update(gce.NetworkProjectID(), f.Name, f).Do()
|
||||
if err != nil {
|
||||
return mc.Observe(err)
|
||||
}
|
||||
|
||||
return gce.waitForGlobalOpInProject(op, gce.NetworkProjectID(), mc)
|
||||
return mc.Observe(gce.c.Firewalls().Update(context.Background(), meta.GlobalKey(f.Name), f))
|
||||
}
|
||||
|
73
vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/gce_forwardingrule.go
generated
vendored
73
vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/gce_forwardingrule.go
generated
vendored
@ -17,8 +17,13 @@ limitations under the License.
|
||||
package gce
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
computealpha "google.golang.org/api/compute/v0.alpha"
|
||||
compute "google.golang.org/api/compute/v1"
|
||||
"k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud"
|
||||
"k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud/filter"
|
||||
"k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud/meta"
|
||||
)
|
||||
|
||||
func newForwardingRuleMetricContext(request, region string) *metricContext {
|
||||
@ -31,79 +36,62 @@ func newForwardingRuleMetricContextWithVersion(request, region, version string)
|
||||
// CreateGlobalForwardingRule creates the passed GlobalForwardingRule
|
||||
func (gce *GCECloud) CreateGlobalForwardingRule(rule *compute.ForwardingRule) error {
|
||||
mc := newForwardingRuleMetricContext("create", "")
|
||||
op, err := gce.service.GlobalForwardingRules.Insert(gce.projectID, rule).Do()
|
||||
if err != nil {
|
||||
return mc.Observe(err)
|
||||
}
|
||||
return gce.waitForGlobalOp(op, mc)
|
||||
return mc.Observe(gce.c.GlobalForwardingRules().Insert(context.Background(), meta.GlobalKey(rule.Name), rule))
|
||||
}
|
||||
|
||||
// SetProxyForGlobalForwardingRule links the given TargetHttp(s)Proxy with the given GlobalForwardingRule.
|
||||
// targetProxyLink is the SelfLink of a TargetHttp(s)Proxy.
|
||||
func (gce *GCECloud) SetProxyForGlobalForwardingRule(forwardingRuleName, targetProxyLink string) error {
|
||||
mc := newForwardingRuleMetricContext("set_proxy", "")
|
||||
op, err := gce.service.GlobalForwardingRules.SetTarget(
|
||||
gce.projectID, forwardingRuleName, &compute.TargetReference{Target: targetProxyLink}).Do()
|
||||
if err != nil {
|
||||
return mc.Observe(err)
|
||||
}
|
||||
|
||||
return gce.waitForGlobalOp(op, mc)
|
||||
target := &compute.TargetReference{Target: targetProxyLink}
|
||||
return mc.Observe(gce.c.GlobalForwardingRules().SetTarget(context.Background(), meta.GlobalKey(forwardingRuleName), target))
|
||||
}
|
||||
|
||||
// DeleteGlobalForwardingRule deletes the GlobalForwardingRule by name.
|
||||
func (gce *GCECloud) DeleteGlobalForwardingRule(name string) error {
|
||||
mc := newForwardingRuleMetricContext("delete", "")
|
||||
op, err := gce.service.GlobalForwardingRules.Delete(gce.projectID, name).Do()
|
||||
if err != nil {
|
||||
return mc.Observe(err)
|
||||
}
|
||||
|
||||
return gce.waitForGlobalOp(op, mc)
|
||||
return mc.Observe(gce.c.GlobalForwardingRules().Delete(context.Background(), meta.GlobalKey(name)))
|
||||
}
|
||||
|
||||
// GetGlobalForwardingRule returns the GlobalForwardingRule by name.
|
||||
func (gce *GCECloud) GetGlobalForwardingRule(name string) (*compute.ForwardingRule, error) {
|
||||
mc := newForwardingRuleMetricContext("get", "")
|
||||
v, err := gce.service.GlobalForwardingRules.Get(gce.projectID, name).Do()
|
||||
v, err := gce.c.GlobalForwardingRules().Get(context.Background(), meta.GlobalKey(name))
|
||||
return v, mc.Observe(err)
|
||||
}
|
||||
|
||||
// ListGlobalForwardingRules lists all GlobalForwardingRules in the project.
|
||||
func (gce *GCECloud) ListGlobalForwardingRules() (*compute.ForwardingRuleList, error) {
|
||||
func (gce *GCECloud) ListGlobalForwardingRules() ([]*compute.ForwardingRule, error) {
|
||||
mc := newForwardingRuleMetricContext("list", "")
|
||||
// TODO: use PageToken to list all not just the first 500
|
||||
v, err := gce.service.GlobalForwardingRules.List(gce.projectID).Do()
|
||||
v, err := gce.c.GlobalForwardingRules().List(context.Background(), filter.None)
|
||||
return v, mc.Observe(err)
|
||||
}
|
||||
|
||||
// GetRegionForwardingRule returns the RegionalForwardingRule by name & region.
|
||||
func (gce *GCECloud) GetRegionForwardingRule(name, region string) (*compute.ForwardingRule, error) {
|
||||
mc := newForwardingRuleMetricContext("get", region)
|
||||
v, err := gce.service.ForwardingRules.Get(gce.projectID, region, name).Do()
|
||||
v, err := gce.c.ForwardingRules().Get(context.Background(), meta.RegionalKey(name, region))
|
||||
return v, mc.Observe(err)
|
||||
}
|
||||
|
||||
// GetAlphaRegionForwardingRule returns the Alpha forwarding rule by name & region.
|
||||
func (gce *GCECloud) GetAlphaRegionForwardingRule(name, region string) (*computealpha.ForwardingRule, error) {
|
||||
mc := newForwardingRuleMetricContextWithVersion("get", region, computeAlphaVersion)
|
||||
v, err := gce.serviceAlpha.ForwardingRules.Get(gce.projectID, region, name).Do()
|
||||
v, err := gce.c.AlphaForwardingRules().Get(context.Background(), meta.RegionalKey(name, region))
|
||||
return v, mc.Observe(err)
|
||||
}
|
||||
|
||||
// ListRegionForwardingRules lists all RegionalForwardingRules in the project & region.
|
||||
func (gce *GCECloud) ListRegionForwardingRules(region string) (*compute.ForwardingRuleList, error) {
|
||||
func (gce *GCECloud) ListRegionForwardingRules(region string) ([]*compute.ForwardingRule, error) {
|
||||
mc := newForwardingRuleMetricContext("list", region)
|
||||
// TODO: use PageToken to list all not just the first 500
|
||||
v, err := gce.service.ForwardingRules.List(gce.projectID, region).Do()
|
||||
v, err := gce.c.ForwardingRules().List(context.Background(), region, filter.None)
|
||||
return v, mc.Observe(err)
|
||||
}
|
||||
|
||||
// ListRegionForwardingRules lists all RegionalForwardingRules in the project & region.
|
||||
func (gce *GCECloud) ListAlphaRegionForwardingRules(region string) (*computealpha.ForwardingRuleList, error) {
|
||||
// ListAlphaRegionForwardingRules lists all RegionalForwardingRules in the project & region.
|
||||
func (gce *GCECloud) ListAlphaRegionForwardingRules(region string) ([]*computealpha.ForwardingRule, error) {
|
||||
mc := newForwardingRuleMetricContextWithVersion("list", region, computeAlphaVersion)
|
||||
// TODO: use PageToken to list all not just the first 500
|
||||
v, err := gce.serviceAlpha.ForwardingRules.List(gce.projectID, region).Do()
|
||||
v, err := gce.c.AlphaForwardingRules().List(context.Background(), region, filter.None)
|
||||
return v, mc.Observe(err)
|
||||
}
|
||||
|
||||
@ -111,41 +99,26 @@ func (gce *GCECloud) ListAlphaRegionForwardingRules(region string) (*computealph
|
||||
// RegionalForwardingRule that points to the given BackendService
|
||||
func (gce *GCECloud) CreateRegionForwardingRule(rule *compute.ForwardingRule, region string) error {
|
||||
mc := newForwardingRuleMetricContext("create", region)
|
||||
op, err := gce.service.ForwardingRules.Insert(gce.projectID, region, rule).Do()
|
||||
if err != nil {
|
||||
return mc.Observe(err)
|
||||
}
|
||||
|
||||
return gce.waitForRegionOp(op, region, mc)
|
||||
return mc.Observe(gce.c.ForwardingRules().Insert(context.Background(), meta.RegionalKey(rule.Name, region), rule))
|
||||
}
|
||||
|
||||
// CreateAlphaRegionForwardingRule creates and returns an Alpha
|
||||
// forwarding fule in the given region.
|
||||
func (gce *GCECloud) CreateAlphaRegionForwardingRule(rule *computealpha.ForwardingRule, region string) error {
|
||||
mc := newForwardingRuleMetricContextWithVersion("create", region, computeAlphaVersion)
|
||||
op, err := gce.serviceAlpha.ForwardingRules.Insert(gce.projectID, region, rule).Do()
|
||||
if err != nil {
|
||||
return mc.Observe(err)
|
||||
}
|
||||
|
||||
return gce.waitForRegionOp(op, region, mc)
|
||||
return mc.Observe(gce.c.AlphaForwardingRules().Insert(context.Background(), meta.RegionalKey(rule.Name, region), rule))
|
||||
}
|
||||
|
||||
// DeleteRegionForwardingRule deletes the RegionalForwardingRule by name & region.
|
||||
func (gce *GCECloud) DeleteRegionForwardingRule(name, region string) error {
|
||||
mc := newForwardingRuleMetricContext("delete", region)
|
||||
op, err := gce.service.ForwardingRules.Delete(gce.projectID, region, name).Do()
|
||||
if err != nil {
|
||||
return mc.Observe(err)
|
||||
}
|
||||
|
||||
return gce.waitForRegionOp(op, region, mc)
|
||||
return mc.Observe(gce.c.ForwardingRules().Delete(context.Background(), meta.RegionalKey(name, region)))
|
||||
}
|
||||
|
||||
// TODO(#51665): retire this function once Network Tiers becomes Beta in GCP.
|
||||
func (gce *GCECloud) getNetworkTierFromForwardingRule(name, region string) (string, error) {
|
||||
if !gce.AlphaFeatureGate.Enabled(AlphaFeatureNetworkTiers) {
|
||||
return NetworkTierDefault.ToGCEValue(), nil
|
||||
return cloud.NetworkTierDefault.ToGCEValue(), nil
|
||||
}
|
||||
fwdRule, err := gce.GetAlphaRegionForwardingRule(name, region)
|
||||
if err != nil {
|
||||
|
138
vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/gce_forwardingrule_fakes.go
generated
vendored
138
vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/gce_forwardingrule_fakes.go
generated
vendored
@ -1,138 +0,0 @@
|
||||
/*
|
||||
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 (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/http"
|
||||
|
||||
computealpha "google.golang.org/api/compute/v0.alpha"
|
||||
compute "google.golang.org/api/compute/v1"
|
||||
"google.golang.org/api/googleapi"
|
||||
)
|
||||
|
||||
type FakeCloudForwardingRuleService struct {
|
||||
// fwdRulesByRegionAndName
|
||||
// Outer key is for region string; inner key is for fwdRuleess name.
|
||||
fwdRulesByRegionAndName map[string]map[string]*computealpha.ForwardingRule
|
||||
}
|
||||
|
||||
// FakeCloudForwardingRuleService Implements CloudForwardingRuleService
|
||||
var _ CloudForwardingRuleService = &FakeCloudForwardingRuleService{}
|
||||
|
||||
func NewFakeCloudForwardingRuleService() *FakeCloudForwardingRuleService {
|
||||
return &FakeCloudForwardingRuleService{
|
||||
fwdRulesByRegionAndName: make(map[string]map[string]*computealpha.ForwardingRule),
|
||||
}
|
||||
}
|
||||
|
||||
// SetRegionalForwardingRulees sets the fwdRuleesses of ther region. This is used for
|
||||
// setting the test environment.
|
||||
func (f *FakeCloudForwardingRuleService) SetRegionalForwardingRulees(region string, fwdRules []*computealpha.ForwardingRule) {
|
||||
// Reset fwdRuleesses in the region.
|
||||
f.fwdRulesByRegionAndName[region] = make(map[string]*computealpha.ForwardingRule)
|
||||
|
||||
for _, fwdRule := range fwdRules {
|
||||
f.fwdRulesByRegionAndName[region][fwdRule.Name] = fwdRule
|
||||
}
|
||||
}
|
||||
|
||||
func (f *FakeCloudForwardingRuleService) CreateAlphaRegionForwardingRule(fwdRule *computealpha.ForwardingRule, region string) error {
|
||||
if _, exists := f.fwdRulesByRegionAndName[region]; !exists {
|
||||
f.fwdRulesByRegionAndName[region] = make(map[string]*computealpha.ForwardingRule)
|
||||
}
|
||||
|
||||
if _, exists := f.fwdRulesByRegionAndName[region][fwdRule.Name]; exists {
|
||||
return &googleapi.Error{Code: http.StatusConflict}
|
||||
}
|
||||
|
||||
f.fwdRulesByRegionAndName[region][fwdRule.Name] = fwdRule
|
||||
return nil
|
||||
}
|
||||
|
||||
func (f *FakeCloudForwardingRuleService) CreateRegionForwardingRule(fwdRule *compute.ForwardingRule, region string) error {
|
||||
alphafwdRule := convertToAlphaForwardingRule(fwdRule)
|
||||
return f.CreateAlphaRegionForwardingRule(alphafwdRule, region)
|
||||
}
|
||||
|
||||
func (f *FakeCloudForwardingRuleService) DeleteRegionForwardingRule(name, region string) error {
|
||||
if _, exists := f.fwdRulesByRegionAndName[region]; !exists {
|
||||
return makeGoogleAPINotFoundError("")
|
||||
}
|
||||
|
||||
if _, exists := f.fwdRulesByRegionAndName[region][name]; !exists {
|
||||
return makeGoogleAPINotFoundError("")
|
||||
}
|
||||
delete(f.fwdRulesByRegionAndName[region], name)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (f *FakeCloudForwardingRuleService) GetAlphaRegionForwardingRule(name, region string) (*computealpha.ForwardingRule, error) {
|
||||
if _, exists := f.fwdRulesByRegionAndName[region]; !exists {
|
||||
return nil, makeGoogleAPINotFoundError("")
|
||||
}
|
||||
|
||||
if fwdRule, exists := f.fwdRulesByRegionAndName[region][name]; !exists {
|
||||
return nil, makeGoogleAPINotFoundError("")
|
||||
} else {
|
||||
return fwdRule, nil
|
||||
}
|
||||
}
|
||||
|
||||
func (f *FakeCloudForwardingRuleService) GetRegionForwardingRule(name, region string) (*compute.ForwardingRule, error) {
|
||||
fwdRule, err := f.GetAlphaRegionForwardingRule(name, region)
|
||||
if fwdRule != nil {
|
||||
return convertToV1ForwardingRule(fwdRule), err
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
|
||||
func (f *FakeCloudForwardingRuleService) getNetworkTierFromForwardingRule(name, region string) (string, error) {
|
||||
fwdRule, err := f.GetAlphaRegionForwardingRule(name, region)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return fwdRule.NetworkTier, nil
|
||||
}
|
||||
|
||||
func convertToV1ForwardingRule(object gceObject) *compute.ForwardingRule {
|
||||
enc, err := object.MarshalJSON()
|
||||
if err != nil {
|
||||
panic(fmt.Sprintf("Failed to encode to json: %v", err))
|
||||
}
|
||||
var fwdRule compute.ForwardingRule
|
||||
if err := json.Unmarshal(enc, &fwdRule); err != nil {
|
||||
panic(fmt.Sprintf("Failed to convert GCE apiObject %v to v1 fwdRuleess: %v", object, err))
|
||||
}
|
||||
return &fwdRule
|
||||
}
|
||||
|
||||
func convertToAlphaForwardingRule(object gceObject) *computealpha.ForwardingRule {
|
||||
enc, err := object.MarshalJSON()
|
||||
if err != nil {
|
||||
panic(fmt.Sprintf("Failed to encode to json: %v", err))
|
||||
}
|
||||
var fwdRule computealpha.ForwardingRule
|
||||
if err := json.Unmarshal(enc, &fwdRule); err != nil {
|
||||
panic(fmt.Sprintf("Failed to convert GCE apiObject %v to alpha fwdRuleess: %v", object, err))
|
||||
}
|
||||
// Set the default values for the Alpha fields.
|
||||
fwdRule.NetworkTier = NetworkTierDefault.ToGCEValue()
|
||||
|
||||
return &fwdRule
|
||||
}
|
115
vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/gce_healthchecks.go
generated
vendored
115
vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/gce_healthchecks.go
generated
vendored
@ -17,13 +17,18 @@ limitations under the License.
|
||||
package gce
|
||||
|
||||
import (
|
||||
"k8s.io/api/core/v1"
|
||||
"k8s.io/kubernetes/pkg/master/ports"
|
||||
utilversion "k8s.io/kubernetes/pkg/util/version"
|
||||
"context"
|
||||
|
||||
"github.com/golang/glog"
|
||||
|
||||
computealpha "google.golang.org/api/compute/v0.alpha"
|
||||
compute "google.golang.org/api/compute/v1"
|
||||
|
||||
"k8s.io/api/core/v1"
|
||||
"k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud/filter"
|
||||
"k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud/meta"
|
||||
"k8s.io/kubernetes/pkg/master/ports"
|
||||
utilversion "k8s.io/kubernetes/pkg/util/version"
|
||||
)
|
||||
|
||||
const (
|
||||
@ -54,48 +59,32 @@ func newHealthcheckMetricContextWithVersion(request, version string) *metricCont
|
||||
// GetHttpHealthCheck returns the given HttpHealthCheck by name.
|
||||
func (gce *GCECloud) GetHttpHealthCheck(name string) (*compute.HttpHealthCheck, error) {
|
||||
mc := newHealthcheckMetricContext("get_legacy")
|
||||
v, err := gce.service.HttpHealthChecks.Get(gce.projectID, name).Do()
|
||||
v, err := gce.c.HttpHealthChecks().Get(context.Background(), meta.GlobalKey(name))
|
||||
return v, mc.Observe(err)
|
||||
}
|
||||
|
||||
// UpdateHttpHealthCheck applies the given HttpHealthCheck as an update.
|
||||
func (gce *GCECloud) UpdateHttpHealthCheck(hc *compute.HttpHealthCheck) error {
|
||||
mc := newHealthcheckMetricContext("update_legacy")
|
||||
op, err := gce.service.HttpHealthChecks.Update(gce.projectID, hc.Name, hc).Do()
|
||||
if err != nil {
|
||||
return mc.Observe(err)
|
||||
}
|
||||
|
||||
return gce.waitForGlobalOp(op, mc)
|
||||
return mc.Observe(gce.c.HttpHealthChecks().Update(context.Background(), meta.GlobalKey(hc.Name), hc))
|
||||
}
|
||||
|
||||
// DeleteHttpHealthCheck deletes the given HttpHealthCheck by name.
|
||||
func (gce *GCECloud) DeleteHttpHealthCheck(name string) error {
|
||||
mc := newHealthcheckMetricContext("delete_legacy")
|
||||
op, err := gce.service.HttpHealthChecks.Delete(gce.projectID, name).Do()
|
||||
if err != nil {
|
||||
return mc.Observe(err)
|
||||
}
|
||||
|
||||
return gce.waitForGlobalOp(op, mc)
|
||||
return mc.Observe(gce.c.HttpHealthChecks().Delete(context.Background(), meta.GlobalKey(name)))
|
||||
}
|
||||
|
||||
// CreateHttpHealthCheck creates the given HttpHealthCheck.
|
||||
func (gce *GCECloud) CreateHttpHealthCheck(hc *compute.HttpHealthCheck) error {
|
||||
mc := newHealthcheckMetricContext("create_legacy")
|
||||
op, err := gce.service.HttpHealthChecks.Insert(gce.projectID, hc).Do()
|
||||
if err != nil {
|
||||
return mc.Observe(err)
|
||||
}
|
||||
|
||||
return gce.waitForGlobalOp(op, mc)
|
||||
return mc.Observe(gce.c.HttpHealthChecks().Insert(context.Background(), meta.GlobalKey(hc.Name), hc))
|
||||
}
|
||||
|
||||
// ListHttpHealthChecks lists all HttpHealthChecks in the project.
|
||||
func (gce *GCECloud) ListHttpHealthChecks() (*compute.HttpHealthCheckList, error) {
|
||||
func (gce *GCECloud) ListHttpHealthChecks() ([]*compute.HttpHealthCheck, error) {
|
||||
mc := newHealthcheckMetricContext("list_legacy")
|
||||
// TODO: use PageToken to list all not just the first 500
|
||||
v, err := gce.service.HttpHealthChecks.List(gce.projectID).Do()
|
||||
v, err := gce.c.HttpHealthChecks().List(context.Background(), filter.None)
|
||||
return v, mc.Observe(err)
|
||||
}
|
||||
|
||||
@ -104,50 +93,32 @@ func (gce *GCECloud) ListHttpHealthChecks() (*compute.HttpHealthCheckList, error
|
||||
// GetHttpsHealthCheck returns the given HttpsHealthCheck by name.
|
||||
func (gce *GCECloud) GetHttpsHealthCheck(name string) (*compute.HttpsHealthCheck, error) {
|
||||
mc := newHealthcheckMetricContext("get_legacy")
|
||||
v, err := gce.service.HttpsHealthChecks.Get(gce.projectID, name).Do()
|
||||
mc.Observe(err)
|
||||
return v, err
|
||||
v, err := gce.c.HttpsHealthChecks().Get(context.Background(), meta.GlobalKey(name))
|
||||
return v, mc.Observe(err)
|
||||
}
|
||||
|
||||
// UpdateHttpsHealthCheck applies the given HttpsHealthCheck as an update.
|
||||
func (gce *GCECloud) UpdateHttpsHealthCheck(hc *compute.HttpsHealthCheck) error {
|
||||
mc := newHealthcheckMetricContext("update_legacy")
|
||||
op, err := gce.service.HttpsHealthChecks.Update(gce.projectID, hc.Name, hc).Do()
|
||||
if err != nil {
|
||||
mc.Observe(err)
|
||||
return err
|
||||
}
|
||||
|
||||
return gce.waitForGlobalOp(op, mc)
|
||||
return mc.Observe(gce.c.HttpsHealthChecks().Update(context.Background(), meta.GlobalKey(hc.Name), hc))
|
||||
}
|
||||
|
||||
// DeleteHttpsHealthCheck deletes the given HttpsHealthCheck by name.
|
||||
func (gce *GCECloud) DeleteHttpsHealthCheck(name string) error {
|
||||
mc := newHealthcheckMetricContext("delete_legacy")
|
||||
op, err := gce.service.HttpsHealthChecks.Delete(gce.projectID, name).Do()
|
||||
if err != nil {
|
||||
return mc.Observe(err)
|
||||
}
|
||||
|
||||
return gce.waitForGlobalOp(op, mc)
|
||||
return mc.Observe(gce.c.HttpsHealthChecks().Delete(context.Background(), meta.GlobalKey(name)))
|
||||
}
|
||||
|
||||
// CreateHttpsHealthCheck creates the given HttpsHealthCheck.
|
||||
func (gce *GCECloud) CreateHttpsHealthCheck(hc *compute.HttpsHealthCheck) error {
|
||||
mc := newHealthcheckMetricContext("create_legacy")
|
||||
op, err := gce.service.HttpsHealthChecks.Insert(gce.projectID, hc).Do()
|
||||
if err != nil {
|
||||
return mc.Observe(err)
|
||||
}
|
||||
|
||||
return gce.waitForGlobalOp(op, mc)
|
||||
return mc.Observe(gce.c.HttpsHealthChecks().Insert(context.Background(), meta.GlobalKey(hc.Name), hc))
|
||||
}
|
||||
|
||||
// ListHttpsHealthChecks lists all HttpsHealthChecks in the project.
|
||||
func (gce *GCECloud) ListHttpsHealthChecks() (*compute.HttpsHealthCheckList, error) {
|
||||
func (gce *GCECloud) ListHttpsHealthChecks() ([]*compute.HttpsHealthCheck, error) {
|
||||
mc := newHealthcheckMetricContext("list_legacy")
|
||||
// TODO: use PageToken to list all not just the first 500
|
||||
v, err := gce.service.HttpsHealthChecks.List(gce.projectID).Do()
|
||||
v, err := gce.c.HttpsHealthChecks().List(context.Background(), filter.None)
|
||||
return v, mc.Observe(err)
|
||||
}
|
||||
|
||||
@ -156,77 +127,51 @@ func (gce *GCECloud) ListHttpsHealthChecks() (*compute.HttpsHealthCheckList, err
|
||||
// GetHealthCheck returns the given HealthCheck by name.
|
||||
func (gce *GCECloud) GetHealthCheck(name string) (*compute.HealthCheck, error) {
|
||||
mc := newHealthcheckMetricContext("get")
|
||||
v, err := gce.service.HealthChecks.Get(gce.projectID, name).Do()
|
||||
v, err := gce.c.HealthChecks().Get(context.Background(), meta.GlobalKey(name))
|
||||
return v, mc.Observe(err)
|
||||
}
|
||||
|
||||
// GetAlphaHealthCheck returns the given alpha HealthCheck by name.
|
||||
func (gce *GCECloud) GetAlphaHealthCheck(name string) (*computealpha.HealthCheck, error) {
|
||||
mc := newHealthcheckMetricContextWithVersion("get", computeAlphaVersion)
|
||||
v, err := gce.serviceAlpha.HealthChecks.Get(gce.projectID, name).Do()
|
||||
v, err := gce.c.AlphaHealthChecks().Get(context.Background(), meta.GlobalKey(name))
|
||||
return v, mc.Observe(err)
|
||||
}
|
||||
|
||||
// UpdateHealthCheck applies the given HealthCheck as an update.
|
||||
func (gce *GCECloud) UpdateHealthCheck(hc *compute.HealthCheck) error {
|
||||
mc := newHealthcheckMetricContext("update")
|
||||
op, err := gce.service.HealthChecks.Update(gce.projectID, hc.Name, hc).Do()
|
||||
if err != nil {
|
||||
return mc.Observe(err)
|
||||
}
|
||||
|
||||
return gce.waitForGlobalOp(op, mc)
|
||||
return mc.Observe(gce.c.HealthChecks().Update(context.Background(), meta.GlobalKey(hc.Name), hc))
|
||||
}
|
||||
|
||||
// UpdateAlphaHealthCheck applies the given alpha HealthCheck as an update.
|
||||
func (gce *GCECloud) UpdateAlphaHealthCheck(hc *computealpha.HealthCheck) error {
|
||||
mc := newHealthcheckMetricContextWithVersion("update", computeAlphaVersion)
|
||||
op, err := gce.serviceAlpha.HealthChecks.Update(gce.projectID, hc.Name, hc).Do()
|
||||
if err != nil {
|
||||
return mc.Observe(err)
|
||||
}
|
||||
|
||||
return gce.waitForGlobalOp(op, mc)
|
||||
return mc.Observe(gce.c.AlphaHealthChecks().Update(context.Background(), meta.GlobalKey(hc.Name), hc))
|
||||
}
|
||||
|
||||
// DeleteHealthCheck deletes the given HealthCheck by name.
|
||||
func (gce *GCECloud) DeleteHealthCheck(name string) error {
|
||||
mc := newHealthcheckMetricContext("delete")
|
||||
op, err := gce.service.HealthChecks.Delete(gce.projectID, name).Do()
|
||||
if err != nil {
|
||||
return mc.Observe(err)
|
||||
}
|
||||
|
||||
return gce.waitForGlobalOp(op, mc)
|
||||
return mc.Observe(gce.c.HealthChecks().Delete(context.Background(), meta.GlobalKey(name)))
|
||||
}
|
||||
|
||||
// CreateHealthCheck creates the given HealthCheck.
|
||||
func (gce *GCECloud) CreateHealthCheck(hc *compute.HealthCheck) error {
|
||||
mc := newHealthcheckMetricContext("create")
|
||||
op, err := gce.service.HealthChecks.Insert(gce.projectID, hc).Do()
|
||||
if err != nil {
|
||||
return mc.Observe(err)
|
||||
}
|
||||
|
||||
return gce.waitForGlobalOp(op, mc)
|
||||
return mc.Observe(gce.c.HealthChecks().Insert(context.Background(), meta.GlobalKey(hc.Name), hc))
|
||||
}
|
||||
|
||||
// CreateAlphaHealthCheck creates the given alpha HealthCheck.
|
||||
func (gce *GCECloud) CreateAlphaHealthCheck(hc *computealpha.HealthCheck) error {
|
||||
mc := newHealthcheckMetricContextWithVersion("create", computeAlphaVersion)
|
||||
op, err := gce.serviceAlpha.HealthChecks.Insert(gce.projectID, hc).Do()
|
||||
if err != nil {
|
||||
return mc.Observe(err)
|
||||
}
|
||||
|
||||
return gce.waitForGlobalOp(op, mc)
|
||||
return mc.Observe(gce.c.AlphaHealthChecks().Insert(context.Background(), meta.GlobalKey(hc.Name), hc))
|
||||
}
|
||||
|
||||
// ListHealthChecks lists all HealthCheck in the project.
|
||||
func (gce *GCECloud) ListHealthChecks() (*compute.HealthCheckList, error) {
|
||||
func (gce *GCECloud) ListHealthChecks() ([]*compute.HealthCheck, error) {
|
||||
mc := newHealthcheckMetricContext("list")
|
||||
// TODO: use PageToken to list all not just the first 500
|
||||
v, err := gce.service.HealthChecks.List(gce.projectID).Do()
|
||||
v, err := gce.c.HealthChecks().List(context.Background(), filter.None)
|
||||
return v, mc.Observe(err)
|
||||
}
|
||||
|
||||
|
77
vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/gce_instancegroup.go
generated
vendored
77
vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/gce_instancegroup.go
generated
vendored
@ -16,7 +16,14 @@ limitations under the License.
|
||||
|
||||
package gce
|
||||
|
||||
import compute "google.golang.org/api/compute/v1"
|
||||
import (
|
||||
"context"
|
||||
|
||||
compute "google.golang.org/api/compute/v1"
|
||||
|
||||
"k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud/filter"
|
||||
"k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud/meta"
|
||||
)
|
||||
|
||||
func newInstanceGroupMetricContext(request string, zone string) *metricContext {
|
||||
return newGenericMetricContext("instancegroup", request, unusedMetricLabel, zone, computeV1Version)
|
||||
@ -26,43 +33,29 @@ func newInstanceGroupMetricContext(request string, zone string) *metricContext {
|
||||
// instances. It is the callers responsibility to add named ports.
|
||||
func (gce *GCECloud) CreateInstanceGroup(ig *compute.InstanceGroup, zone string) error {
|
||||
mc := newInstanceGroupMetricContext("create", zone)
|
||||
op, err := gce.service.InstanceGroups.Insert(gce.projectID, zone, ig).Do()
|
||||
if err != nil {
|
||||
return mc.Observe(err)
|
||||
}
|
||||
|
||||
return gce.waitForZoneOp(op, zone, mc)
|
||||
return mc.Observe(gce.c.InstanceGroups().Insert(context.Background(), meta.ZonalKey(ig.Name, zone), ig))
|
||||
}
|
||||
|
||||
// DeleteInstanceGroup deletes an instance group.
|
||||
func (gce *GCECloud) DeleteInstanceGroup(name string, zone string) error {
|
||||
mc := newInstanceGroupMetricContext("delete", zone)
|
||||
op, err := gce.service.InstanceGroups.Delete(
|
||||
gce.projectID, zone, name).Do()
|
||||
if err != nil {
|
||||
return mc.Observe(err)
|
||||
}
|
||||
|
||||
return gce.waitForZoneOp(op, zone, mc)
|
||||
return mc.Observe(gce.c.InstanceGroups().Delete(context.Background(), meta.ZonalKey(name, zone)))
|
||||
}
|
||||
|
||||
// ListInstanceGroups lists all InstanceGroups in the project and
|
||||
// zone.
|
||||
func (gce *GCECloud) ListInstanceGroups(zone string) (*compute.InstanceGroupList, error) {
|
||||
func (gce *GCECloud) ListInstanceGroups(zone string) ([]*compute.InstanceGroup, error) {
|
||||
mc := newInstanceGroupMetricContext("list", zone)
|
||||
// TODO: use PageToken to list all not just the first 500
|
||||
v, err := gce.service.InstanceGroups.List(gce.projectID, zone).Do()
|
||||
v, err := gce.c.InstanceGroups().List(context.Background(), zone, filter.None)
|
||||
return v, mc.Observe(err)
|
||||
}
|
||||
|
||||
// ListInstancesInInstanceGroup lists all the instances in a given
|
||||
// instance group and state.
|
||||
func (gce *GCECloud) ListInstancesInInstanceGroup(name string, zone string, state string) (*compute.InstanceGroupsListInstances, error) {
|
||||
func (gce *GCECloud) ListInstancesInInstanceGroup(name string, zone string, state string) ([]*compute.InstanceWithNamedPorts, error) {
|
||||
mc := newInstanceGroupMetricContext("list_instances", zone)
|
||||
// TODO: use PageToken to list all not just the first 500
|
||||
v, err := gce.service.InstanceGroups.ListInstances(
|
||||
gce.projectID, zone, name,
|
||||
&compute.InstanceGroupsListInstancesRequest{InstanceState: state}).Do()
|
||||
req := &compute.InstanceGroupsListInstancesRequest{InstanceState: state}
|
||||
v, err := gce.c.InstanceGroups().ListInstances(context.Background(), meta.ZonalKey(name, zone), req, filter.None)
|
||||
return v, mc.Observe(err)
|
||||
}
|
||||
|
||||
@ -70,58 +63,40 @@ func (gce *GCECloud) ListInstancesInInstanceGroup(name string, zone string, stat
|
||||
// instance group.
|
||||
func (gce *GCECloud) AddInstancesToInstanceGroup(name string, zone string, instanceRefs []*compute.InstanceReference) error {
|
||||
mc := newInstanceGroupMetricContext("add_instances", zone)
|
||||
// TODO: should cull operation above this layer.
|
||||
if len(instanceRefs) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
op, err := gce.service.InstanceGroups.AddInstances(
|
||||
gce.projectID, zone, name,
|
||||
&compute.InstanceGroupsAddInstancesRequest{
|
||||
Instances: instanceRefs,
|
||||
}).Do()
|
||||
if err != nil {
|
||||
return mc.Observe(err)
|
||||
req := &compute.InstanceGroupsAddInstancesRequest{
|
||||
Instances: instanceRefs,
|
||||
}
|
||||
|
||||
return gce.waitForZoneOp(op, zone, mc)
|
||||
return mc.Observe(gce.c.InstanceGroups().AddInstances(context.Background(), meta.ZonalKey(name, zone), req))
|
||||
}
|
||||
|
||||
// RemoveInstancesFromInstanceGroup removes the given instances from
|
||||
// the instance group.
|
||||
func (gce *GCECloud) RemoveInstancesFromInstanceGroup(name string, zone string, instanceRefs []*compute.InstanceReference) error {
|
||||
mc := newInstanceGroupMetricContext("remove_instances", zone)
|
||||
// TODO: should cull operation above this layer.
|
||||
if len(instanceRefs) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
op, err := gce.service.InstanceGroups.RemoveInstances(
|
||||
gce.projectID, zone, name,
|
||||
&compute.InstanceGroupsRemoveInstancesRequest{
|
||||
Instances: instanceRefs,
|
||||
}).Do()
|
||||
if err != nil {
|
||||
return mc.Observe(err)
|
||||
req := &compute.InstanceGroupsRemoveInstancesRequest{
|
||||
Instances: instanceRefs,
|
||||
}
|
||||
|
||||
return gce.waitForZoneOp(op, zone, mc)
|
||||
return mc.Observe(gce.c.InstanceGroups().RemoveInstances(context.Background(), meta.ZonalKey(name, zone), req))
|
||||
}
|
||||
|
||||
// SetNamedPortsOfInstanceGroup sets the list of named ports on a given instance group
|
||||
func (gce *GCECloud) SetNamedPortsOfInstanceGroup(igName, zone string, namedPorts []*compute.NamedPort) error {
|
||||
mc := newInstanceGroupMetricContext("set_namedports", zone)
|
||||
op, err := gce.service.InstanceGroups.SetNamedPorts(
|
||||
gce.projectID, zone, igName,
|
||||
&compute.InstanceGroupsSetNamedPortsRequest{NamedPorts: namedPorts}).Do()
|
||||
if err != nil {
|
||||
return mc.Observe(err)
|
||||
}
|
||||
|
||||
return gce.waitForZoneOp(op, zone, mc)
|
||||
req := &compute.InstanceGroupsSetNamedPortsRequest{NamedPorts: namedPorts}
|
||||
return mc.Observe(gce.c.InstanceGroups().SetNamedPorts(context.Background(), meta.ZonalKey(igName, zone), req))
|
||||
}
|
||||
|
||||
// GetInstanceGroup returns an instance group by name.
|
||||
func (gce *GCECloud) GetInstanceGroup(name string, zone string) (*compute.InstanceGroup, error) {
|
||||
mc := newInstanceGroupMetricContext("get", zone)
|
||||
v, err := gce.service.InstanceGroups.Get(gce.projectID, zone, name).Do()
|
||||
v, err := gce.c.InstanceGroups().Get(context.Background(), meta.ZonalKey(name, zone))
|
||||
return v, mc.Observe(err)
|
||||
}
|
||||
|
289
vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/gce_instances.go
generated
vendored
289
vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/gce_instances.go
generated
vendored
@ -17,6 +17,7 @@ limitations under the License.
|
||||
package gce
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"net"
|
||||
"net/http"
|
||||
@ -26,7 +27,6 @@ import (
|
||||
|
||||
"cloud.google.com/go/compute/metadata"
|
||||
"github.com/golang/glog"
|
||||
computealpha "google.golang.org/api/compute/v0.alpha"
|
||||
computebeta "google.golang.org/api/compute/v0.beta"
|
||||
compute "google.golang.org/api/compute/v1"
|
||||
|
||||
@ -35,6 +35,8 @@ import (
|
||||
"k8s.io/apimachinery/pkg/util/sets"
|
||||
"k8s.io/apimachinery/pkg/util/wait"
|
||||
"k8s.io/kubernetes/pkg/cloudprovider"
|
||||
"k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud/filter"
|
||||
"k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud/meta"
|
||||
kubeletapis "k8s.io/kubernetes/pkg/kubelet/apis"
|
||||
)
|
||||
|
||||
@ -65,6 +67,11 @@ func getZone(n *v1.Node) string {
|
||||
return zone
|
||||
}
|
||||
|
||||
func makeHostURL(projectsApiEndpoint, projectID, zone, host string) string {
|
||||
host = canonicalizeInstanceName(host)
|
||||
return projectsApiEndpoint + strings.Join([]string{projectID, "zones", zone, "instances", host}, "/")
|
||||
}
|
||||
|
||||
// ToInstanceReferences returns instance references by links
|
||||
func (gce *GCECloud) ToInstanceReferences(zone string, instanceNames []string) (refs []*compute.InstanceReference) {
|
||||
for _, ins := range instanceNames {
|
||||
@ -75,7 +82,7 @@ func (gce *GCECloud) ToInstanceReferences(zone string, instanceNames []string) (
|
||||
}
|
||||
|
||||
// NodeAddresses is an implementation of Instances.NodeAddresses.
|
||||
func (gce *GCECloud) NodeAddresses(_ types.NodeName) ([]v1.NodeAddress, error) {
|
||||
func (gce *GCECloud) NodeAddresses(_ context.Context, _ types.NodeName) ([]v1.NodeAddress, error) {
|
||||
internalIP, err := metadata.Get("instance/network-interfaces/0/ip")
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("couldn't get internal IP: %v", err)
|
||||
@ -90,15 +97,15 @@ func (gce *GCECloud) NodeAddresses(_ types.NodeName) ([]v1.NodeAddress, error) {
|
||||
}, nil
|
||||
}
|
||||
|
||||
// This method will not be called from the node that is requesting this ID.
|
||||
// NodeAddressesByProviderID will not be called from the node that is requesting this ID.
|
||||
// i.e. metadata service and other local methods cannot be used here
|
||||
func (gce *GCECloud) NodeAddressesByProviderID(providerID string) ([]v1.NodeAddress, error) {
|
||||
project, zone, name, err := splitProviderID(providerID)
|
||||
func (gce *GCECloud) NodeAddressesByProviderID(ctx context.Context, providerID string) ([]v1.NodeAddress, error) {
|
||||
_, zone, name, err := splitProviderID(providerID)
|
||||
if err != nil {
|
||||
return []v1.NodeAddress{}, err
|
||||
}
|
||||
|
||||
instance, err := gce.service.Instances.Get(project, zone, canonicalizeInstanceName(name)).Do()
|
||||
instance, err := gce.c.Instances().Get(context.Background(), meta.ZonalKey(canonicalizeInstanceName(name), zone))
|
||||
if err != nil {
|
||||
return []v1.NodeAddress{}, fmt.Errorf("error while querying for providerID %q: %v", providerID, err)
|
||||
}
|
||||
@ -139,7 +146,7 @@ func (gce *GCECloud) instanceByProviderID(providerID string) (*gceInstance, erro
|
||||
// with the specified unique providerID This method will not be called from the
|
||||
// node that is requesting this ID. i.e. metadata service and other local
|
||||
// methods cannot be used here
|
||||
func (gce *GCECloud) InstanceTypeByProviderID(providerID string) (string, error) {
|
||||
func (gce *GCECloud) InstanceTypeByProviderID(ctx context.Context, providerID string) (string, error) {
|
||||
instance, err := gce.instanceByProviderID(providerID)
|
||||
if err != nil {
|
||||
return "", err
|
||||
@ -149,7 +156,7 @@ func (gce *GCECloud) InstanceTypeByProviderID(providerID string) (string, error)
|
||||
}
|
||||
|
||||
// ExternalID returns the cloud provider ID of the node with the specified NodeName (deprecated).
|
||||
func (gce *GCECloud) ExternalID(nodeName types.NodeName) (string, error) {
|
||||
func (gce *GCECloud) ExternalID(ctx context.Context, nodeName types.NodeName) (string, error) {
|
||||
instanceName := mapNodeNameToInstanceName(nodeName)
|
||||
if gce.useMetadataServer {
|
||||
// Use metadata, if possible, to fetch ID. See issue #12000
|
||||
@ -171,7 +178,7 @@ func (gce *GCECloud) ExternalID(nodeName types.NodeName) (string, error) {
|
||||
|
||||
// InstanceExistsByProviderID returns true if the instance with the given provider id still exists and is running.
|
||||
// If false is returned with no error, the instance will be immediately deleted by the cloud controller manager.
|
||||
func (gce *GCECloud) InstanceExistsByProviderID(providerID string) (bool, error) {
|
||||
func (gce *GCECloud) InstanceExistsByProviderID(ctx context.Context, providerID string) (bool, error) {
|
||||
_, err := gce.instanceByProviderID(providerID)
|
||||
if err != nil {
|
||||
if err == cloudprovider.InstanceNotFound {
|
||||
@ -184,7 +191,7 @@ func (gce *GCECloud) InstanceExistsByProviderID(providerID string) (bool, error)
|
||||
}
|
||||
|
||||
// InstanceID returns the cloud provider ID of the node with the specified NodeName.
|
||||
func (gce *GCECloud) InstanceID(nodeName types.NodeName) (string, error) {
|
||||
func (gce *GCECloud) InstanceID(ctx context.Context, nodeName types.NodeName) (string, error) {
|
||||
instanceName := mapNodeNameToInstanceName(nodeName)
|
||||
if gce.useMetadataServer {
|
||||
// Use metadata, if possible, to fetch ID. See issue #12000
|
||||
@ -203,7 +210,7 @@ func (gce *GCECloud) InstanceID(nodeName types.NodeName) (string, error) {
|
||||
}
|
||||
|
||||
// InstanceType returns the type of the specified node with the specified NodeName.
|
||||
func (gce *GCECloud) InstanceType(nodeName types.NodeName) (string, error) {
|
||||
func (gce *GCECloud) InstanceType(ctx context.Context, nodeName types.NodeName) (string, error) {
|
||||
instanceName := mapNodeNameToInstanceName(nodeName)
|
||||
if gce.useMetadataServer {
|
||||
// Use metadata, if possible, to fetch ID. See issue #12000
|
||||
@ -221,9 +228,9 @@ func (gce *GCECloud) InstanceType(nodeName types.NodeName) (string, error) {
|
||||
return instance.Type, nil
|
||||
}
|
||||
|
||||
func (gce *GCECloud) AddSSHKeyToAllInstances(user string, keyData []byte) error {
|
||||
func (gce *GCECloud) AddSSHKeyToAllInstances(ctx context.Context, user string, keyData []byte) error {
|
||||
return wait.Poll(2*time.Second, 30*time.Second, func() (bool, error) {
|
||||
project, err := gce.service.Projects.Get(gce.projectID).Do()
|
||||
project, err := gce.c.Projects().Get(context.Background(), gce.projectID)
|
||||
if err != nil {
|
||||
glog.Errorf("Could not get project: %v", err)
|
||||
return false, nil
|
||||
@ -254,20 +261,13 @@ func (gce *GCECloud) AddSSHKeyToAllInstances(user string, keyData []byte) error
|
||||
}
|
||||
|
||||
mc := newInstancesMetricContext("add_ssh_key", "")
|
||||
op, err := gce.service.Projects.SetCommonInstanceMetadata(
|
||||
gce.projectID, project.CommonInstanceMetadata).Do()
|
||||
err = gce.c.Projects().SetCommonInstanceMetadata(context.Background(), gce.projectID, project.CommonInstanceMetadata)
|
||||
mc.Observe(err)
|
||||
|
||||
if err != nil {
|
||||
glog.Errorf("Could not Set Metadata: %v", err)
|
||||
mc.Observe(err)
|
||||
return false, nil
|
||||
}
|
||||
|
||||
if err := gce.waitForGlobalOp(op, mc); err != nil {
|
||||
glog.Errorf("Could not Set Metadata: %v", err)
|
||||
return false, nil
|
||||
}
|
||||
|
||||
glog.Infof("Successfully added sshKey to project metadata")
|
||||
return true, nil
|
||||
})
|
||||
@ -282,7 +282,7 @@ func (gce *GCECloud) GetAllCurrentZones() (sets.String, error) {
|
||||
gce.nodeZonesLock.Lock()
|
||||
defer gce.nodeZonesLock.Unlock()
|
||||
if !gce.nodeInformerSynced() {
|
||||
return nil, fmt.Errorf("Node informer is not synced when trying to GetAllCurrentZones")
|
||||
return nil, fmt.Errorf("node informer is not synced when trying to GetAllCurrentZones")
|
||||
}
|
||||
zones := sets.NewString()
|
||||
for zone, nodes := range gce.nodeZones {
|
||||
@ -298,59 +298,50 @@ func (gce *GCECloud) GetAllCurrentZones() (sets.String, error) {
|
||||
// get all zones with compute instances in them even if not k8s instances!!!
|
||||
// ex. I have k8s nodes in us-central1-c and us-central1-b. I also have
|
||||
// a non-k8s compute in us-central1-a. This func will return a,b, and c.
|
||||
//
|
||||
// TODO: this should be removed from the cloud provider.
|
||||
func (gce *GCECloud) GetAllZonesFromCloudProvider() (sets.String, error) {
|
||||
zones := sets.NewString()
|
||||
|
||||
for _, zone := range gce.managedZones {
|
||||
mc := newInstancesMetricContext("list", zone)
|
||||
// We only retrieve one page in each zone - we only care about existence
|
||||
listCall := gce.service.Instances.List(gce.projectID, zone)
|
||||
|
||||
listCall = listCall.Fields("items(name)")
|
||||
res, err := listCall.Do()
|
||||
instances, err := gce.c.Instances().List(context.Background(), zone, filter.None)
|
||||
if err != nil {
|
||||
return nil, mc.Observe(err)
|
||||
return sets.NewString(), err
|
||||
}
|
||||
mc.Observe(nil)
|
||||
|
||||
if len(res.Items) != 0 {
|
||||
if len(instances) > 0 {
|
||||
zones.Insert(zone)
|
||||
}
|
||||
}
|
||||
|
||||
return zones, nil
|
||||
}
|
||||
|
||||
// InsertInstance creates a new instance on GCP
|
||||
func (gce *GCECloud) InsertInstance(project string, zone string, rb *compute.Instance) error {
|
||||
func (gce *GCECloud) InsertInstance(project string, zone string, i *compute.Instance) error {
|
||||
mc := newInstancesMetricContext("create", zone)
|
||||
op, err := gce.service.Instances.Insert(project, zone, rb).Do()
|
||||
if err != nil {
|
||||
return mc.Observe(err)
|
||||
}
|
||||
return gce.waitForZoneOp(op, zone, mc)
|
||||
return mc.Observe(gce.c.Instances().Insert(context.Background(), meta.ZonalKey(i.Name, zone), i))
|
||||
}
|
||||
|
||||
// ListInstanceNames returns a string of instance names seperated by spaces.
|
||||
// ListInstanceNames returns a string of instance names separated by spaces.
|
||||
// This method should only be used for e2e testing.
|
||||
// TODO: remove this method.
|
||||
func (gce *GCECloud) ListInstanceNames(project, zone string) (string, error) {
|
||||
res, err := gce.service.Instances.List(project, zone).Fields("items(name)").Do()
|
||||
l, err := gce.c.Instances().List(context.Background(), zone, filter.None)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
var output string
|
||||
for _, item := range res.Items {
|
||||
output += item.Name + " "
|
||||
var names []string
|
||||
for _, i := range l {
|
||||
names = append(names, i.Name)
|
||||
}
|
||||
return output, nil
|
||||
return strings.Join(names, " "), nil
|
||||
}
|
||||
|
||||
// DeleteInstance deletes an instance specified by project, zone, and name
|
||||
func (gce *GCECloud) DeleteInstance(project, zone, name string) (*compute.Operation, error) {
|
||||
return gce.service.Instances.Delete(project, zone, name).Do()
|
||||
func (gce *GCECloud) DeleteInstance(project, zone, name string) error {
|
||||
return gce.c.Instances().Delete(context.Background(), meta.ZonalKey(name, zone))
|
||||
}
|
||||
|
||||
// Implementation of Instances.CurrentNodeName
|
||||
func (gce *GCECloud) CurrentNodeName(hostname string) (types.NodeName, error) {
|
||||
func (gce *GCECloud) CurrentNodeName(ctx context.Context, hostname string) (types.NodeName, error) {
|
||||
return types.NodeName(hostname), nil
|
||||
}
|
||||
|
||||
@ -365,15 +356,14 @@ func (gce *GCECloud) AliasRanges(nodeName types.NodeName) (cidrs []string, err e
|
||||
}
|
||||
|
||||
var res *computebeta.Instance
|
||||
res, err = gce.serviceBeta.Instances.Get(
|
||||
gce.projectID, instance.Zone, instance.Name).Do()
|
||||
res, err = gce.c.BetaInstances().Get(context.Background(), meta.ZonalKey(instance.Name, lastComponent(instance.Zone)))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
for _, networkInterface := range res.NetworkInterfaces {
|
||||
for _, aliasIpRange := range networkInterface.AliasIpRanges {
|
||||
cidrs = append(cidrs, aliasIpRange.IpCidrRange)
|
||||
for _, r := range networkInterface.AliasIpRanges {
|
||||
cidrs = append(cidrs, r.IpCidrRange)
|
||||
}
|
||||
}
|
||||
return
|
||||
@ -387,110 +377,96 @@ func (gce *GCECloud) AddAliasToInstance(nodeName types.NodeName, alias *net.IPNe
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
instance, err := gce.serviceAlpha.Instances.Get(gce.projectID, v1instance.Zone, v1instance.Name).Do()
|
||||
instance, err := gce.c.BetaInstances().Get(context.Background(), meta.ZonalKey(v1instance.Name, lastComponent(v1instance.Zone)))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
switch len(instance.NetworkInterfaces) {
|
||||
case 0:
|
||||
return fmt.Errorf("Instance %q has no network interfaces", nodeName)
|
||||
return fmt.Errorf("instance %q has no network interfaces", nodeName)
|
||||
case 1:
|
||||
default:
|
||||
glog.Warningf("Instance %q has more than one network interface, using only the first (%v)",
|
||||
nodeName, instance.NetworkInterfaces)
|
||||
}
|
||||
|
||||
iface := instance.NetworkInterfaces[0]
|
||||
iface.AliasIpRanges = append(iface.AliasIpRanges, &computealpha.AliasIpRange{
|
||||
iface := &computebeta.NetworkInterface{}
|
||||
iface.Name = instance.NetworkInterfaces[0].Name
|
||||
iface.Fingerprint = instance.NetworkInterfaces[0].Fingerprint
|
||||
iface.AliasIpRanges = append(iface.AliasIpRanges, &computebeta.AliasIpRange{
|
||||
IpCidrRange: alias.String(),
|
||||
SubnetworkRangeName: gce.secondaryRangeName,
|
||||
})
|
||||
|
||||
mc := newInstancesMetricContext("addalias", v1instance.Zone)
|
||||
op, err := gce.serviceAlpha.Instances.UpdateNetworkInterface(
|
||||
gce.projectID, lastComponent(instance.Zone), instance.Name, iface.Name, iface).Do()
|
||||
if err != nil {
|
||||
return mc.Observe(err)
|
||||
}
|
||||
return gce.waitForZoneOp(op, v1instance.Zone, mc)
|
||||
mc := newInstancesMetricContext("add_alias", v1instance.Zone)
|
||||
err = gce.c.BetaInstances().UpdateNetworkInterface(context.Background(), meta.ZonalKey(instance.Name, lastComponent(instance.Zone)), iface.Name, iface)
|
||||
return mc.Observe(err)
|
||||
}
|
||||
|
||||
// Gets the named instances, returning cloudprovider.InstanceNotFound if any instance is not found
|
||||
// Gets the named instances, returning cloudprovider.InstanceNotFound if any
|
||||
// instance is not found
|
||||
func (gce *GCECloud) getInstancesByNames(names []string) ([]*gceInstance, error) {
|
||||
instances := make(map[string]*gceInstance)
|
||||
found := map[string]*gceInstance{}
|
||||
remaining := len(names)
|
||||
|
||||
nodeInstancePrefix := gce.nodeInstancePrefix
|
||||
for _, name := range names {
|
||||
name = canonicalizeInstanceName(name)
|
||||
if !strings.HasPrefix(name, gce.nodeInstancePrefix) {
|
||||
glog.Warningf("instance '%s' does not conform to prefix '%s', removing filter", name, gce.nodeInstancePrefix)
|
||||
glog.Warningf("Instance %q does not conform to prefix %q, removing filter", name, gce.nodeInstancePrefix)
|
||||
nodeInstancePrefix = ""
|
||||
}
|
||||
instances[name] = nil
|
||||
found[name] = nil
|
||||
}
|
||||
|
||||
for _, zone := range gce.managedZones {
|
||||
if remaining == 0 {
|
||||
break
|
||||
}
|
||||
|
||||
pageToken := ""
|
||||
page := 0
|
||||
for ; page == 0 || (pageToken != "" && page < maxPages); page++ {
|
||||
listCall := gce.service.Instances.List(gce.projectID, zone)
|
||||
|
||||
if nodeInstancePrefix != "" {
|
||||
// Add the filter for hosts
|
||||
listCall = listCall.Filter("name eq " + nodeInstancePrefix + ".*")
|
||||
}
|
||||
|
||||
// TODO(zmerlynn): Internal bug 29524655
|
||||
// listCall = listCall.Fields("items(name,id,disks,machineType)")
|
||||
if pageToken != "" {
|
||||
listCall.PageToken(pageToken)
|
||||
}
|
||||
|
||||
res, err := listCall.Do()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
pageToken = res.NextPageToken
|
||||
for _, i := range res.Items {
|
||||
name := i.Name
|
||||
if _, ok := instances[name]; !ok {
|
||||
continue
|
||||
}
|
||||
|
||||
instance := &gceInstance{
|
||||
Zone: zone,
|
||||
Name: name,
|
||||
ID: i.Id,
|
||||
Disks: i.Disks,
|
||||
Type: lastComponent(i.MachineType),
|
||||
}
|
||||
instances[name] = instance
|
||||
remaining--
|
||||
}
|
||||
instances, err := gce.c.Instances().List(context.Background(), zone, filter.Regexp("name", nodeInstancePrefix+".*"))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if page >= maxPages {
|
||||
glog.Errorf("getInstancesByNames exceeded maxPages=%d for Instances.List: truncating.", maxPages)
|
||||
for _, inst := range instances {
|
||||
if remaining == 0 {
|
||||
break
|
||||
}
|
||||
if _, ok := found[inst.Name]; !ok {
|
||||
continue
|
||||
}
|
||||
if found[inst.Name] != nil {
|
||||
glog.Errorf("Instance name %q was duplicated (in zone %q and %q)", inst.Name, zone, found[inst.Name].Zone)
|
||||
continue
|
||||
}
|
||||
found[inst.Name] = &gceInstance{
|
||||
Zone: zone,
|
||||
Name: inst.Name,
|
||||
ID: inst.Id,
|
||||
Disks: inst.Disks,
|
||||
Type: lastComponent(inst.MachineType),
|
||||
}
|
||||
remaining--
|
||||
}
|
||||
}
|
||||
|
||||
instanceArray := make([]*gceInstance, len(names))
|
||||
for i, name := range names {
|
||||
name = canonicalizeInstanceName(name)
|
||||
instance := instances[name]
|
||||
if instance == nil {
|
||||
glog.Errorf("Failed to retrieve instance: %q", name)
|
||||
return nil, cloudprovider.InstanceNotFound
|
||||
if remaining > 0 {
|
||||
var failed []string
|
||||
for k := range found {
|
||||
if found[k] == nil {
|
||||
failed = append(failed, k)
|
||||
}
|
||||
}
|
||||
instanceArray[i] = instances[name]
|
||||
glog.Errorf("Failed to retrieve instances: %v", failed)
|
||||
return nil, cloudprovider.InstanceNotFound
|
||||
}
|
||||
|
||||
return instanceArray, nil
|
||||
var ret []*gceInstance
|
||||
for _, instance := range found {
|
||||
ret = append(ret, instance)
|
||||
}
|
||||
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
// Gets the named instance, returning cloudprovider.InstanceNotFound if the instance is not found
|
||||
@ -514,12 +490,11 @@ func (gce *GCECloud) getInstanceByName(name string) (*gceInstance, error) {
|
||||
func (gce *GCECloud) getInstanceFromProjectInZoneByName(project, zone, name string) (*gceInstance, error) {
|
||||
name = canonicalizeInstanceName(name)
|
||||
mc := newInstancesMetricContext("get", zone)
|
||||
res, err := gce.service.Instances.Get(project, zone, name).Do()
|
||||
res, err := gce.c.Instances().Get(context.Background(), meta.ZonalKey(name, zone))
|
||||
mc.Observe(err)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &gceInstance{
|
||||
Zone: lastComponent(res.Zone),
|
||||
Name: res.Name,
|
||||
@ -578,16 +553,16 @@ func (gce *GCECloud) isCurrentInstance(instanceID string) bool {
|
||||
// ComputeHostTags grabs all tags from all instances being added to the pool.
|
||||
// * The longest tag that is a prefix of the instance name is used
|
||||
// * If any instance has no matching prefix tag, return error
|
||||
// Invoking this method to get host tags is risky since it depends on the format
|
||||
// of the host names in the cluster. Only use it as a fallback if gce.nodeTags
|
||||
// is unspecified
|
||||
// Invoking this method to get host tags is risky since it depends on the
|
||||
// format of the host names in the cluster. Only use it as a fallback if
|
||||
// gce.nodeTags is unspecified
|
||||
func (gce *GCECloud) computeHostTags(hosts []*gceInstance) ([]string, error) {
|
||||
// TODO: We could store the tags in gceInstance, so we could have already fetched it
|
||||
hostNamesByZone := make(map[string]map[string]bool) // map of zones -> map of names -> bool (for easy lookup)
|
||||
nodeInstancePrefix := gce.nodeInstancePrefix
|
||||
for _, host := range hosts {
|
||||
if !strings.HasPrefix(host.Name, gce.nodeInstancePrefix) {
|
||||
glog.Warningf("instance '%s' does not conform to prefix '%s', ignoring filter", host, gce.nodeInstancePrefix)
|
||||
glog.Warningf("instance %v does not conform to prefix '%s', ignoring filter", host, gce.nodeInstancePrefix)
|
||||
nodeInstancePrefix = ""
|
||||
}
|
||||
|
||||
@ -601,54 +576,34 @@ func (gce *GCECloud) computeHostTags(hosts []*gceInstance) ([]string, error) {
|
||||
|
||||
tags := sets.NewString()
|
||||
|
||||
filt := filter.None
|
||||
if nodeInstancePrefix != "" {
|
||||
filt = filter.Regexp("name", nodeInstancePrefix+".*")
|
||||
}
|
||||
for zone, hostNames := range hostNamesByZone {
|
||||
pageToken := ""
|
||||
page := 0
|
||||
for ; page == 0 || (pageToken != "" && page < maxPages); page++ {
|
||||
listCall := gce.service.Instances.List(gce.projectID, zone)
|
||||
|
||||
if nodeInstancePrefix != "" {
|
||||
// Add the filter for hosts
|
||||
listCall = listCall.Filter("name eq " + nodeInstancePrefix + ".*")
|
||||
}
|
||||
|
||||
// Add the fields we want
|
||||
// TODO(zmerlynn): Internal bug 29524655
|
||||
// listCall = listCall.Fields("items(name,tags)")
|
||||
|
||||
if pageToken != "" {
|
||||
listCall = listCall.PageToken(pageToken)
|
||||
}
|
||||
|
||||
res, err := listCall.Do()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
pageToken = res.NextPageToken
|
||||
for _, instance := range res.Items {
|
||||
if !hostNames[instance.Name] {
|
||||
continue
|
||||
}
|
||||
|
||||
longest_tag := ""
|
||||
for _, tag := range instance.Tags.Items {
|
||||
if strings.HasPrefix(instance.Name, tag) && len(tag) > len(longest_tag) {
|
||||
longest_tag = tag
|
||||
}
|
||||
}
|
||||
if len(longest_tag) > 0 {
|
||||
tags.Insert(longest_tag)
|
||||
} else {
|
||||
return nil, fmt.Errorf("Could not find any tag that is a prefix of instance name for instance %s", instance.Name)
|
||||
}
|
||||
}
|
||||
instances, err := gce.c.Instances().List(context.Background(), zone, filt)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if page >= maxPages {
|
||||
glog.Errorf("computeHostTags exceeded maxPages=%d for Instances.List: truncating.", maxPages)
|
||||
for _, instance := range instances {
|
||||
if !hostNames[instance.Name] {
|
||||
continue
|
||||
}
|
||||
longest_tag := ""
|
||||
for _, tag := range instance.Tags.Items {
|
||||
if strings.HasPrefix(instance.Name, tag) && len(tag) > len(longest_tag) {
|
||||
longest_tag = tag
|
||||
}
|
||||
}
|
||||
if len(longest_tag) > 0 {
|
||||
tags.Insert(longest_tag)
|
||||
} else {
|
||||
return nil, fmt.Errorf("could not find any tag that is a prefix of instance name for instance %s", instance.Name)
|
||||
}
|
||||
}
|
||||
}
|
||||
if len(tags) == 0 {
|
||||
return nil, fmt.Errorf("No instances found")
|
||||
return nil, fmt.Errorf("no instances found")
|
||||
}
|
||||
return tags.List(), nil
|
||||
}
|
||||
|
38
vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/gce_loadbalancer.go
generated
vendored
38
vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/gce_loadbalancer.go
generated
vendored
@ -17,15 +17,18 @@ limitations under the License.
|
||||
package gce
|
||||
|
||||
import (
|
||||
"context"
|
||||
"flag"
|
||||
"fmt"
|
||||
"net"
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
"github.com/golang/glog"
|
||||
|
||||
"k8s.io/api/core/v1"
|
||||
"k8s.io/kubernetes/pkg/cloudprovider"
|
||||
"k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud"
|
||||
netsets "k8s.io/kubernetes/pkg/util/net/sets"
|
||||
)
|
||||
|
||||
@ -42,13 +45,6 @@ func newLoadBalancerMetricContext(request, region string) *metricContext {
|
||||
return newGenericMetricContext("loadbalancer", request, region, unusedMetricLabel, computeV1Version)
|
||||
}
|
||||
|
||||
type lbScheme string
|
||||
|
||||
const (
|
||||
schemeExternal lbScheme = "EXTERNAL"
|
||||
schemeInternal lbScheme = "INTERNAL"
|
||||
)
|
||||
|
||||
func init() {
|
||||
var err error
|
||||
// LB L7 proxies and all L3/4/7 health checkers have client addresses within these known CIDRs.
|
||||
@ -62,7 +58,9 @@ func init() {
|
||||
|
||||
// String is the method to format the flag's value, part of the flag.Value interface.
|
||||
func (c *cidrs) String() string {
|
||||
return strings.Join(c.ipn.StringSlice(), ",")
|
||||
s := c.ipn.StringSlice()
|
||||
sort.Strings(s)
|
||||
return strings.Join(s, ",")
|
||||
}
|
||||
|
||||
// Set supports a value of CSV or the flag repeated multiple times
|
||||
@ -93,7 +91,7 @@ func LoadBalancerSrcRanges() []string {
|
||||
}
|
||||
|
||||
// GetLoadBalancer is an implementation of LoadBalancer.GetLoadBalancer
|
||||
func (gce *GCECloud) GetLoadBalancer(clusterName string, svc *v1.Service) (*v1.LoadBalancerStatus, bool, error) {
|
||||
func (gce *GCECloud) GetLoadBalancer(ctx context.Context, clusterName string, svc *v1.Service) (*v1.LoadBalancerStatus, bool, error) {
|
||||
loadBalancerName := cloudprovider.GetLoadBalancerName(svc)
|
||||
fwd, err := gce.GetRegionForwardingRule(loadBalancerName, gce.region)
|
||||
if err == nil {
|
||||
@ -106,7 +104,7 @@ func (gce *GCECloud) GetLoadBalancer(clusterName string, svc *v1.Service) (*v1.L
|
||||
}
|
||||
|
||||
// EnsureLoadBalancer is an implementation of LoadBalancer.EnsureLoadBalancer.
|
||||
func (gce *GCECloud) EnsureLoadBalancer(clusterName string, svc *v1.Service, nodes []*v1.Node) (*v1.LoadBalancerStatus, error) {
|
||||
func (gce *GCECloud) EnsureLoadBalancer(ctx context.Context, clusterName string, svc *v1.Service, nodes []*v1.Node) (*v1.LoadBalancerStatus, error) {
|
||||
loadBalancerName := cloudprovider.GetLoadBalancerName(svc)
|
||||
desiredScheme := getSvcScheme(svc)
|
||||
clusterID, err := gce.ClusterID.GetID()
|
||||
@ -122,13 +120,13 @@ func (gce *GCECloud) EnsureLoadBalancer(clusterName string, svc *v1.Service, nod
|
||||
}
|
||||
|
||||
if existingFwdRule != nil {
|
||||
existingScheme := lbScheme(strings.ToUpper(existingFwdRule.LoadBalancingScheme))
|
||||
existingScheme := cloud.LbScheme(strings.ToUpper(existingFwdRule.LoadBalancingScheme))
|
||||
|
||||
// If the loadbalancer type changes between INTERNAL and EXTERNAL, the old load balancer should be deleted.
|
||||
if existingScheme != desiredScheme {
|
||||
glog.V(4).Infof("EnsureLoadBalancer(%v, %v, %v, %v, %v): deleting existing %v loadbalancer", clusterName, svc.Namespace, svc.Name, loadBalancerName, gce.region, existingScheme)
|
||||
switch existingScheme {
|
||||
case schemeInternal:
|
||||
case cloud.SchemeInternal:
|
||||
err = gce.ensureInternalLoadBalancerDeleted(clusterName, clusterID, svc)
|
||||
default:
|
||||
err = gce.ensureExternalLoadBalancerDeleted(clusterName, clusterID, svc)
|
||||
@ -145,7 +143,7 @@ func (gce *GCECloud) EnsureLoadBalancer(clusterName string, svc *v1.Service, nod
|
||||
|
||||
var status *v1.LoadBalancerStatus
|
||||
switch desiredScheme {
|
||||
case schemeInternal:
|
||||
case cloud.SchemeInternal:
|
||||
status, err = gce.ensureInternalLoadBalancer(clusterName, clusterID, svc, existingFwdRule, nodes)
|
||||
default:
|
||||
status, err = gce.ensureExternalLoadBalancer(clusterName, clusterID, svc, existingFwdRule, nodes)
|
||||
@ -155,7 +153,7 @@ func (gce *GCECloud) EnsureLoadBalancer(clusterName string, svc *v1.Service, nod
|
||||
}
|
||||
|
||||
// UpdateLoadBalancer is an implementation of LoadBalancer.UpdateLoadBalancer.
|
||||
func (gce *GCECloud) UpdateLoadBalancer(clusterName string, svc *v1.Service, nodes []*v1.Node) error {
|
||||
func (gce *GCECloud) UpdateLoadBalancer(ctx context.Context, clusterName string, svc *v1.Service, nodes []*v1.Node) error {
|
||||
loadBalancerName := cloudprovider.GetLoadBalancerName(svc)
|
||||
scheme := getSvcScheme(svc)
|
||||
clusterID, err := gce.ClusterID.GetID()
|
||||
@ -166,7 +164,7 @@ func (gce *GCECloud) UpdateLoadBalancer(clusterName string, svc *v1.Service, nod
|
||||
glog.V(4).Infof("UpdateLoadBalancer(%v, %v, %v, %v, %v): updating with %d nodes", clusterName, svc.Namespace, svc.Name, loadBalancerName, gce.region, len(nodes))
|
||||
|
||||
switch scheme {
|
||||
case schemeInternal:
|
||||
case cloud.SchemeInternal:
|
||||
err = gce.updateInternalLoadBalancer(clusterName, clusterID, svc, nodes)
|
||||
default:
|
||||
err = gce.updateExternalLoadBalancer(clusterName, svc, nodes)
|
||||
@ -176,7 +174,7 @@ func (gce *GCECloud) UpdateLoadBalancer(clusterName string, svc *v1.Service, nod
|
||||
}
|
||||
|
||||
// EnsureLoadBalancerDeleted is an implementation of LoadBalancer.EnsureLoadBalancerDeleted.
|
||||
func (gce *GCECloud) EnsureLoadBalancerDeleted(clusterName string, svc *v1.Service) error {
|
||||
func (gce *GCECloud) EnsureLoadBalancerDeleted(ctx context.Context, clusterName string, svc *v1.Service) error {
|
||||
loadBalancerName := cloudprovider.GetLoadBalancerName(svc)
|
||||
scheme := getSvcScheme(svc)
|
||||
clusterID, err := gce.ClusterID.GetID()
|
||||
@ -187,7 +185,7 @@ func (gce *GCECloud) EnsureLoadBalancerDeleted(clusterName string, svc *v1.Servi
|
||||
glog.V(4).Infof("EnsureLoadBalancerDeleted(%v, %v, %v, %v, %v): deleting loadbalancer", clusterName, svc.Namespace, svc.Name, loadBalancerName, gce.region)
|
||||
|
||||
switch scheme {
|
||||
case schemeInternal:
|
||||
case cloud.SchemeInternal:
|
||||
err = gce.ensureInternalLoadBalancerDeleted(clusterName, clusterID, svc)
|
||||
default:
|
||||
err = gce.ensureExternalLoadBalancerDeleted(clusterName, clusterID, svc)
|
||||
@ -196,9 +194,9 @@ func (gce *GCECloud) EnsureLoadBalancerDeleted(clusterName string, svc *v1.Servi
|
||||
return err
|
||||
}
|
||||
|
||||
func getSvcScheme(svc *v1.Service) lbScheme {
|
||||
func getSvcScheme(svc *v1.Service) cloud.LbScheme {
|
||||
if typ, ok := GetLoadBalancerAnnotationType(svc); ok && typ == LBTypeInternal {
|
||||
return schemeInternal
|
||||
return cloud.SchemeInternal
|
||||
}
|
||||
return schemeExternal
|
||||
return cloud.SchemeExternal
|
||||
}
|
||||
|
177
vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/gce_loadbalancer_external.go
generated
vendored
177
vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/gce_loadbalancer_external.go
generated
vendored
@ -28,6 +28,7 @@ import (
|
||||
"k8s.io/apimachinery/pkg/util/sets"
|
||||
apiservice "k8s.io/kubernetes/pkg/api/v1/service"
|
||||
"k8s.io/kubernetes/pkg/cloudprovider"
|
||||
"k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud"
|
||||
netsets "k8s.io/kubernetes/pkg/util/net/sets"
|
||||
|
||||
"github.com/golang/glog"
|
||||
@ -63,8 +64,6 @@ func (gce *GCECloud) ensureExternalLoadBalancer(clusterName, clusterID string, a
|
||||
portStr = append(portStr, fmt.Sprintf("%s/%d", p.Protocol, p.Port))
|
||||
}
|
||||
|
||||
affinityType := apiService.Spec.SessionAffinity
|
||||
|
||||
serviceName := types.NamespacedName{Namespace: apiService.Namespace, Name: apiService.Name}
|
||||
lbRefStr := fmt.Sprintf("%v(%v)", loadBalancerName, serviceName)
|
||||
glog.V(2).Infof("ensureExternalLoadBalancer(%s, %v, %v, %v, %v, %v)", lbRefStr, gce.region, requestedIP, portStr, hostNames, apiService.Annotations)
|
||||
@ -192,7 +191,7 @@ func (gce *GCECloud) ensureExternalLoadBalancer(clusterName, clusterID string, a
|
||||
}
|
||||
}
|
||||
|
||||
tpExists, tpNeedsUpdate, err := gce.targetPoolNeedsUpdate(loadBalancerName, gce.region, affinityType)
|
||||
tpExists, tpNeedsRecreation, err := gce.targetPoolNeedsRecreation(loadBalancerName, gce.region, apiService.Spec.SessionAffinity)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -211,24 +210,24 @@ func (gce *GCECloud) ensureExternalLoadBalancer(clusterName, clusterID string, a
|
||||
glog.V(4).Infof("ensureExternalLoadBalancer(%s): Service needs local traffic health checks on: %d%s.", lbRefStr, healthCheckNodePort, path)
|
||||
if hcLocalTrafficExisting == nil {
|
||||
// This logic exists to detect a transition for non-OnlyLocal to OnlyLocal service
|
||||
// turn on the tpNeedsUpdate flag to delete/recreate fwdrule/tpool updating the
|
||||
// turn on the tpNeedsRecreation flag to delete/recreate fwdrule/tpool updating the
|
||||
// target pool to use local traffic health check.
|
||||
glog.V(2).Infof("ensureExternalLoadBalancer(%s): Updating from nodes health checks to local traffic health checks.", lbRefStr)
|
||||
if supportsNodesHealthCheck {
|
||||
hcToDelete = makeHttpHealthCheck(MakeNodesHealthCheckName(clusterID), GetNodesHealthCheckPath(), GetNodesHealthCheckPort())
|
||||
}
|
||||
tpNeedsUpdate = true
|
||||
tpNeedsRecreation = true
|
||||
}
|
||||
hcToCreate = makeHttpHealthCheck(loadBalancerName, path, healthCheckNodePort)
|
||||
} else {
|
||||
glog.V(4).Infof("ensureExternalLoadBalancer(%s): Service needs nodes health checks.", lbRefStr)
|
||||
if hcLocalTrafficExisting != nil {
|
||||
// This logic exists to detect a transition from OnlyLocal to non-OnlyLocal service
|
||||
// and turn on the tpNeedsUpdate flag to delete/recreate fwdrule/tpool updating the
|
||||
// and turn on the tpNeedsRecreation flag to delete/recreate fwdrule/tpool updating the
|
||||
// target pool to use nodes health check.
|
||||
glog.V(2).Infof("ensureExternalLoadBalancer(%s): Updating from local traffic health checks to nodes health checks.", lbRefStr)
|
||||
hcToDelete = hcLocalTrafficExisting
|
||||
tpNeedsUpdate = true
|
||||
tpNeedsRecreation = true
|
||||
}
|
||||
if supportsNodesHealthCheck {
|
||||
hcToCreate = makeHttpHealthCheck(MakeNodesHealthCheckName(clusterID), GetNodesHealthCheckPath(), GetNodesHealthCheckPort())
|
||||
@ -241,7 +240,7 @@ func (gce *GCECloud) ensureExternalLoadBalancer(clusterName, clusterID string, a
|
||||
// can't delete a target pool that's currently in use by a forwarding rule.
|
||||
// Thus, we have to tear down the forwarding rule if either it or the target
|
||||
// pool needs to be updated.
|
||||
if fwdRuleExists && (fwdRuleNeedsUpdate || tpNeedsUpdate) {
|
||||
if fwdRuleExists && (fwdRuleNeedsUpdate || tpNeedsRecreation) {
|
||||
// Begin critical section. If we have to delete the forwarding rule,
|
||||
// and something should fail before we recreate it, don't release the
|
||||
// IP. That way we can come back to it later.
|
||||
@ -251,48 +250,12 @@ func (gce *GCECloud) ensureExternalLoadBalancer(clusterName, clusterID string, a
|
||||
}
|
||||
glog.Infof("ensureExternalLoadBalancer(%s): Deleted forwarding rule.", lbRefStr)
|
||||
}
|
||||
if tpExists && tpNeedsUpdate {
|
||||
// Pass healthchecks to DeleteExternalTargetPoolAndChecks to cleanup health checks after cleaning up the target pool itself.
|
||||
var hcNames []string
|
||||
if hcToDelete != nil {
|
||||
hcNames = append(hcNames, hcToDelete.Name)
|
||||
}
|
||||
if err := gce.DeleteExternalTargetPoolAndChecks(apiService, loadBalancerName, gce.region, clusterID, hcNames...); err != nil {
|
||||
return nil, fmt.Errorf("failed to delete existing target pool for load balancer (%s) update: %v", lbRefStr, err)
|
||||
}
|
||||
glog.Infof("ensureExternalLoadBalancer(%s): Deleted target pool.", lbRefStr)
|
||||
|
||||
if err := gce.ensureTargetPoolAndHealthCheck(tpExists, tpNeedsRecreation, apiService, loadBalancerName, clusterID, ipAddressToUse, hosts, hcToCreate, hcToDelete); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Once we've deleted the resources (if necessary), build them back up (or for
|
||||
// the first time if they're new).
|
||||
if tpNeedsUpdate {
|
||||
createInstances := hosts
|
||||
if len(hosts) > maxTargetPoolCreateInstances {
|
||||
createInstances = createInstances[:maxTargetPoolCreateInstances]
|
||||
}
|
||||
// Pass healthchecks to createTargetPool which needs them as health check links in the target pool
|
||||
if err := gce.createTargetPool(apiService, loadBalancerName, serviceName.String(), ipAddressToUse, gce.region, clusterID, createInstances, affinityType, hcToCreate); err != nil {
|
||||
return nil, fmt.Errorf("failed to create target pool for load balancer (%s): %v", lbRefStr, err)
|
||||
}
|
||||
if hcToCreate != nil {
|
||||
glog.Infof("ensureExternalLoadBalancer(%s): Created health checks %v.", lbRefStr, hcToCreate.Name)
|
||||
}
|
||||
if len(hosts) <= maxTargetPoolCreateInstances {
|
||||
glog.Infof("ensureExternalLoadBalancer(%s): Created target pool.", lbRefStr)
|
||||
} else {
|
||||
glog.Infof("ensureExternalLoadBalancer(%s): Created initial target pool (now updating with %d hosts).", lbRefStr, len(hosts)-maxTargetPoolCreateInstances)
|
||||
|
||||
created := sets.NewString()
|
||||
for _, host := range createInstances {
|
||||
created.Insert(host.makeComparableHostPath())
|
||||
}
|
||||
if err := gce.updateTargetPool(loadBalancerName, created, hosts); err != nil {
|
||||
return nil, fmt.Errorf("failed to update target pool for load balancer (%s): %v", lbRefStr, err)
|
||||
}
|
||||
glog.Infof("ensureExternalLoadBalancer(%s): Updated target pool (with %d hosts).", lbRefStr, len(hosts)-maxTargetPoolCreateInstances)
|
||||
}
|
||||
}
|
||||
if tpNeedsUpdate || fwdRuleNeedsUpdate {
|
||||
if tpNeedsRecreation || fwdRuleNeedsUpdate {
|
||||
glog.Infof("ensureExternalLoadBalancer(%s): Creating forwarding rule, IP %s (tier: %s).", lbRefStr, ipAddressToUse, netTier)
|
||||
if err := createForwardingRule(gce, loadBalancerName, serviceName.String(), gce.region, ipAddressToUse, gce.targetPoolURL(loadBalancerName), ports, netTier); err != nil {
|
||||
return nil, fmt.Errorf("failed to create forwarding rule for load balancer (%s): %v", lbRefStr, err)
|
||||
@ -319,16 +282,7 @@ func (gce *GCECloud) updateExternalLoadBalancer(clusterName string, service *v1.
|
||||
}
|
||||
|
||||
loadBalancerName := cloudprovider.GetLoadBalancerName(service)
|
||||
pool, err := gce.service.TargetPools.Get(gce.projectID, gce.region, loadBalancerName).Do()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
existing := sets.NewString()
|
||||
for _, instance := range pool.Instances {
|
||||
existing.Insert(hostURLToComparablePath(instance))
|
||||
}
|
||||
|
||||
return gce.updateTargetPool(loadBalancerName, existing, hosts)
|
||||
return gce.updateTargetPool(loadBalancerName, hosts)
|
||||
}
|
||||
|
||||
// ensureExternalLoadBalancerDeleted is the external implementation of LoadBalancer.EnsureLoadBalancerDeleted
|
||||
@ -463,7 +417,7 @@ func (gce *GCECloud) DeleteExternalTargetPoolAndChecks(service *v1.Service, name
|
||||
// the verification failed. It also returns a boolean to indicate whether the
|
||||
// IP address is considered owned by the user (i.e., not managed by the
|
||||
// controller.
|
||||
func verifyUserRequestedIP(s CloudAddressService, region, requestedIP, fwdRuleIP, lbRef string, desiredNetTier NetworkTier) (isUserOwnedIP bool, err error) {
|
||||
func verifyUserRequestedIP(s CloudAddressService, region, requestedIP, fwdRuleIP, lbRef string, desiredNetTier cloud.NetworkTier) (isUserOwnedIP bool, err error) {
|
||||
if requestedIP == "" {
|
||||
return false, nil
|
||||
}
|
||||
@ -486,7 +440,7 @@ func verifyUserRequestedIP(s CloudAddressService, region, requestedIP, fwdRuleIP
|
||||
if err != nil {
|
||||
return false, fmt.Errorf("failed to check the network tier of the IP %q: %v", requestedIP, err)
|
||||
}
|
||||
netTier := NetworkTierGCEValueToType(netTierStr)
|
||||
netTier := cloud.NetworkTierGCEValueToType(netTierStr)
|
||||
if netTier != desiredNetTier {
|
||||
glog.Errorf("verifyUserRequestedIP: requested static IP %q (name: %s) for LB %s has network tier %s, need %s.", requestedIP, existingAddress.Name, lbRef, netTier, desiredNetTier)
|
||||
return false, fmt.Errorf("requrested IP %q belongs to the %s network tier; expected %s", requestedIP, netTier, desiredNetTier)
|
||||
@ -508,7 +462,54 @@ func verifyUserRequestedIP(s CloudAddressService, region, requestedIP, fwdRuleIP
|
||||
return false, fmt.Errorf("requested ip %q is neither static nor assigned to the LB", requestedIP)
|
||||
}
|
||||
|
||||
func (gce *GCECloud) createTargetPool(svc *v1.Service, name, serviceName, ipAddress, region, clusterID string, hosts []*gceInstance, affinityType v1.ServiceAffinity, hc *compute.HttpHealthCheck) error {
|
||||
func (gce *GCECloud) ensureTargetPoolAndHealthCheck(tpExists, tpNeedsRecreation bool, svc *v1.Service, loadBalancerName, clusterID, ipAddressToUse string, hosts []*gceInstance, hcToCreate, hcToDelete *compute.HttpHealthCheck) error {
|
||||
serviceName := types.NamespacedName{Namespace: svc.Namespace, Name: svc.Name}
|
||||
lbRefStr := fmt.Sprintf("%v(%v)", loadBalancerName, serviceName)
|
||||
|
||||
if tpExists && tpNeedsRecreation {
|
||||
// Pass healthchecks to DeleteExternalTargetPoolAndChecks to cleanup health checks after cleaning up the target pool itself.
|
||||
var hcNames []string
|
||||
if hcToDelete != nil {
|
||||
hcNames = append(hcNames, hcToDelete.Name)
|
||||
}
|
||||
if err := gce.DeleteExternalTargetPoolAndChecks(svc, loadBalancerName, gce.region, clusterID, hcNames...); err != nil {
|
||||
return fmt.Errorf("failed to delete existing target pool for load balancer (%s) update: %v", lbRefStr, err)
|
||||
}
|
||||
glog.Infof("ensureTargetPoolAndHealthCheck(%s): Deleted target pool.", lbRefStr)
|
||||
}
|
||||
// Once we've deleted the resources (if necessary), build them back up (or for
|
||||
// the first time if they're new).
|
||||
if tpNeedsRecreation {
|
||||
createInstances := hosts
|
||||
if len(hosts) > maxTargetPoolCreateInstances {
|
||||
createInstances = createInstances[:maxTargetPoolCreateInstances]
|
||||
}
|
||||
if err := gce.createTargetPoolAndHealthCheck(svc, loadBalancerName, serviceName.String(), ipAddressToUse, gce.region, clusterID, createInstances, hcToCreate); err != nil {
|
||||
return fmt.Errorf("failed to create target pool for load balancer (%s): %v", lbRefStr, err)
|
||||
}
|
||||
if hcToCreate != nil {
|
||||
glog.Infof("ensureTargetPoolAndHealthCheck(%s): Created health checks %v.", lbRefStr, hcToCreate.Name)
|
||||
}
|
||||
if len(hosts) <= maxTargetPoolCreateInstances {
|
||||
glog.Infof("ensureTargetPoolAndHealthCheck(%s): Created target pool.", lbRefStr)
|
||||
} else {
|
||||
glog.Infof("ensureTargetPoolAndHealthCheck(%s): Created initial target pool (now updating the remaining %d hosts).", lbRefStr, len(hosts)-maxTargetPoolCreateInstances)
|
||||
if err := gce.updateTargetPool(loadBalancerName, hosts); err != nil {
|
||||
return fmt.Errorf("failed to update target pool for load balancer (%s): %v", lbRefStr, err)
|
||||
}
|
||||
glog.Infof("ensureTargetPoolAndHealthCheck(%s): Updated target pool (with %d hosts).", lbRefStr, len(hosts)-maxTargetPoolCreateInstances)
|
||||
}
|
||||
} else if tpExists {
|
||||
// Ensure hosts are updated even if there is no other changes required on target pool.
|
||||
if err := gce.updateTargetPool(loadBalancerName, hosts); err != nil {
|
||||
return fmt.Errorf("failed to update target pool for load balancer (%s): %v", lbRefStr, err)
|
||||
}
|
||||
glog.Infof("ensureTargetPoolAndHealthCheck(%s): Updated target pool (with %d hosts).", lbRefStr, len(hosts))
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (gce *GCECloud) createTargetPoolAndHealthCheck(svc *v1.Service, name, serviceName, ipAddress, region, clusterID string, hosts []*gceInstance, hc *compute.HttpHealthCheck) error {
|
||||
// health check management is coupled with targetPools to prevent leaks. A
|
||||
// target pool is the only thing that requires a health check, so we delete
|
||||
// associated checks on teardown, and ensure checks on setup.
|
||||
@ -535,14 +536,14 @@ func (gce *GCECloud) createTargetPool(svc *v1.Service, name, serviceName, ipAddr
|
||||
|
||||
var instances []string
|
||||
for _, host := range hosts {
|
||||
instances = append(instances, makeHostURL(gce.service.BasePath, gce.projectID, host.Zone, host.Name))
|
||||
instances = append(instances, host.makeComparableHostPath())
|
||||
}
|
||||
glog.Infof("Creating targetpool %v with %d healthchecks", name, len(hcLinks))
|
||||
pool := &compute.TargetPool{
|
||||
Name: name,
|
||||
Description: fmt.Sprintf(`{"kubernetes.io/service-name":"%s"}`, serviceName),
|
||||
Instances: instances,
|
||||
SessionAffinity: translateAffinityType(affinityType),
|
||||
SessionAffinity: translateAffinityType(svc.Spec.SessionAffinity),
|
||||
HealthChecks: hcLinks,
|
||||
}
|
||||
|
||||
@ -552,7 +553,16 @@ func (gce *GCECloud) createTargetPool(svc *v1.Service, name, serviceName, ipAddr
|
||||
return nil
|
||||
}
|
||||
|
||||
func (gce *GCECloud) updateTargetPool(loadBalancerName string, existing sets.String, hosts []*gceInstance) error {
|
||||
func (gce *GCECloud) updateTargetPool(loadBalancerName string, hosts []*gceInstance) error {
|
||||
pool, err := gce.GetTargetPool(loadBalancerName, gce.region)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
existing := sets.NewString()
|
||||
for _, instance := range pool.Instances {
|
||||
existing.Insert(hostURLToComparablePath(instance))
|
||||
}
|
||||
|
||||
var toAdd []*compute.InstanceReference
|
||||
var toRemove []*compute.InstanceReference
|
||||
for _, host := range hosts {
|
||||
@ -648,7 +658,7 @@ func (gce *GCECloud) ensureHttpHealthCheck(name, path string, port int32) (hc *c
|
||||
// Returns whether the forwarding rule exists, whether it needs to be updated,
|
||||
// what its IP address is (if it exists), and any error we encountered.
|
||||
func (gce *GCECloud) forwardingRuleNeedsUpdate(name, region string, loadBalancerIP string, ports []v1.ServicePort) (exists bool, needsUpdate bool, ipAddress string, err error) {
|
||||
fwd, err := gce.service.ForwardingRules.Get(gce.projectID, region, name).Do()
|
||||
fwd, err := gce.GetRegionForwardingRule(name, region)
|
||||
if err != nil {
|
||||
if isHTTPErrorCode(err, http.StatusNotFound) {
|
||||
return false, true, "", nil
|
||||
@ -686,8 +696,8 @@ func (gce *GCECloud) forwardingRuleNeedsUpdate(name, region string, loadBalancer
|
||||
|
||||
// Doesn't check whether the hosts have changed, since host updating is handled
|
||||
// separately.
|
||||
func (gce *GCECloud) targetPoolNeedsUpdate(name, region string, affinityType v1.ServiceAffinity) (exists bool, needsUpdate bool, err error) {
|
||||
tp, err := gce.service.TargetPools.Get(gce.projectID, region, name).Do()
|
||||
func (gce *GCECloud) targetPoolNeedsRecreation(name, region string, affinityType v1.ServiceAffinity) (exists bool, needsRecreation bool, err error) {
|
||||
tp, err := gce.GetTargetPool(name, region)
|
||||
if err != nil {
|
||||
if isHTTPErrorCode(err, http.StatusNotFound) {
|
||||
return false, true, nil
|
||||
@ -723,11 +733,6 @@ func nodeNames(nodes []*v1.Node) []string {
|
||||
return ret
|
||||
}
|
||||
|
||||
func makeHostURL(projectsApiEndpoint, projectID, zone, host string) string {
|
||||
host = canonicalizeInstanceName(host)
|
||||
return projectsApiEndpoint + strings.Join([]string{projectID, "zones", zone, "instances", host}, "/")
|
||||
}
|
||||
|
||||
func hostURLToComparablePath(hostURL string) string {
|
||||
idx := strings.Index(hostURL, "/zones/")
|
||||
if idx < 0 {
|
||||
@ -773,7 +778,7 @@ func translateAffinityType(affinityType v1.ServiceAffinity) string {
|
||||
}
|
||||
|
||||
func (gce *GCECloud) firewallNeedsUpdate(name, serviceName, region, ipAddress string, ports []v1.ServicePort, sourceRanges netsets.IPNet) (exists bool, needsUpdate bool, err error) {
|
||||
fw, err := gce.service.Firewalls.Get(gce.NetworkProjectID(), MakeFirewallName(name)).Do()
|
||||
fw, err := gce.GetFirewall(MakeFirewallName(name))
|
||||
if err != nil {
|
||||
if isHTTPErrorCode(err, http.StatusNotFound) {
|
||||
return false, true, nil
|
||||
@ -820,7 +825,7 @@ func (gce *GCECloud) ensureHttpHealthCheckFirewall(svc *v1.Service, serviceName,
|
||||
ports := []v1.ServicePort{{Protocol: "tcp", Port: hcPort}}
|
||||
|
||||
fwName := MakeHealthCheckFirewallName(clusterID, hcName, isNodesHealthCheck)
|
||||
fw, err := gce.service.Firewalls.Get(gce.NetworkProjectID(), fwName).Do()
|
||||
fw, err := gce.GetFirewall(fwName)
|
||||
if err != nil {
|
||||
if !isHTTPErrorCode(err, http.StatusNotFound) {
|
||||
return fmt.Errorf("error getting firewall for health checks: %v", err)
|
||||
@ -848,7 +853,7 @@ func (gce *GCECloud) ensureHttpHealthCheckFirewall(svc *v1.Service, serviceName,
|
||||
return nil
|
||||
}
|
||||
|
||||
func createForwardingRule(s CloudForwardingRuleService, name, serviceName, region, ipAddress, target string, ports []v1.ServicePort, netTier NetworkTier) error {
|
||||
func createForwardingRule(s CloudForwardingRuleService, name, serviceName, region, ipAddress, target string, ports []v1.ServicePort, netTier cloud.NetworkTier) error {
|
||||
portRange, err := loadBalancerPortRange(ports)
|
||||
if err != nil {
|
||||
return err
|
||||
@ -857,7 +862,7 @@ func createForwardingRule(s CloudForwardingRuleService, name, serviceName, regio
|
||||
ipProtocol := string(ports[0].Protocol)
|
||||
|
||||
switch netTier {
|
||||
case NetworkTierPremium:
|
||||
case cloud.NetworkTierPremium:
|
||||
rule := &compute.ForwardingRule{
|
||||
Name: name,
|
||||
Description: desc,
|
||||
@ -960,7 +965,7 @@ func (gce *GCECloud) firewallObject(name, region, desc string, sourceRanges nets
|
||||
return firewall, nil
|
||||
}
|
||||
|
||||
func ensureStaticIP(s CloudAddressService, name, serviceName, region, existingIP string, netTier NetworkTier) (ipAddress string, existing bool, err error) {
|
||||
func ensureStaticIP(s CloudAddressService, name, serviceName, region, existingIP string, netTier cloud.NetworkTier) (ipAddress string, existing bool, err error) {
|
||||
// If the address doesn't exist, this will create it.
|
||||
// If the existingIP exists but is ephemeral, this will promote it to static.
|
||||
// If the address already exists, this will harmlessly return a StatusConflict
|
||||
@ -970,7 +975,7 @@ func ensureStaticIP(s CloudAddressService, name, serviceName, region, existingIP
|
||||
|
||||
var creationErr error
|
||||
switch netTier {
|
||||
case NetworkTierPremium:
|
||||
case cloud.NetworkTierPremium:
|
||||
addressObj := &compute.Address{
|
||||
Name: name,
|
||||
Description: desc,
|
||||
@ -1008,19 +1013,19 @@ func ensureStaticIP(s CloudAddressService, name, serviceName, region, existingIP
|
||||
return addr.Address, existed, nil
|
||||
}
|
||||
|
||||
func (gce *GCECloud) getServiceNetworkTier(svc *v1.Service) (NetworkTier, error) {
|
||||
func (gce *GCECloud) getServiceNetworkTier(svc *v1.Service) (cloud.NetworkTier, error) {
|
||||
if !gce.AlphaFeatureGate.Enabled(AlphaFeatureNetworkTiers) {
|
||||
return NetworkTierDefault, nil
|
||||
return cloud.NetworkTierDefault, nil
|
||||
}
|
||||
tier, err := GetServiceNetworkTier(svc)
|
||||
if err != nil {
|
||||
// Returns an error if the annotation is invalid.
|
||||
return NetworkTier(""), err
|
||||
return cloud.NetworkTier(""), err
|
||||
}
|
||||
return tier, nil
|
||||
}
|
||||
|
||||
func (gce *GCECloud) deleteWrongNetworkTieredResources(lbName, lbRef string, desiredNetTier NetworkTier) error {
|
||||
func (gce *GCECloud) deleteWrongNetworkTieredResources(lbName, lbRef string, desiredNetTier cloud.NetworkTier) error {
|
||||
logPrefix := fmt.Sprintf("deleteWrongNetworkTieredResources:(%s)", lbRef)
|
||||
if err := deleteFWDRuleWithWrongTier(gce, gce.region, lbName, logPrefix, desiredNetTier); err != nil {
|
||||
return err
|
||||
@ -1033,14 +1038,14 @@ func (gce *GCECloud) deleteWrongNetworkTieredResources(lbName, lbRef string, des
|
||||
|
||||
// deleteFWDRuleWithWrongTier checks the network tier of existing forwarding
|
||||
// rule and delete the rule if the tier does not matched the desired tier.
|
||||
func deleteFWDRuleWithWrongTier(s CloudForwardingRuleService, region, name, logPrefix string, desiredNetTier NetworkTier) error {
|
||||
func deleteFWDRuleWithWrongTier(s CloudForwardingRuleService, region, name, logPrefix string, desiredNetTier cloud.NetworkTier) error {
|
||||
tierStr, err := s.getNetworkTierFromForwardingRule(name, region)
|
||||
if isNotFound(err) {
|
||||
return nil
|
||||
} else if err != nil {
|
||||
return err
|
||||
}
|
||||
existingTier := NetworkTierGCEValueToType(tierStr)
|
||||
existingTier := cloud.NetworkTierGCEValueToType(tierStr)
|
||||
if existingTier == desiredNetTier {
|
||||
return nil
|
||||
}
|
||||
@ -1052,7 +1057,7 @@ func deleteFWDRuleWithWrongTier(s CloudForwardingRuleService, region, name, logP
|
||||
|
||||
// deleteAddressWithWrongTier checks the network tier of existing address
|
||||
// and delete the address if the tier does not matched the desired tier.
|
||||
func deleteAddressWithWrongTier(s CloudAddressService, region, name, logPrefix string, desiredNetTier NetworkTier) error {
|
||||
func deleteAddressWithWrongTier(s CloudAddressService, region, name, logPrefix string, desiredNetTier cloud.NetworkTier) error {
|
||||
// We only check the IP address matching the reserved name that the
|
||||
// controller assigned to the LB. We make the assumption that an address of
|
||||
// such name is owned by the controller and is safe to release. Whether an
|
||||
@ -1068,7 +1073,7 @@ func deleteAddressWithWrongTier(s CloudAddressService, region, name, logPrefix s
|
||||
} else if err != nil {
|
||||
return err
|
||||
}
|
||||
existingTier := NetworkTierGCEValueToType(tierStr)
|
||||
existingTier := cloud.NetworkTierGCEValueToType(tierStr)
|
||||
if existingTier == desiredNetTier {
|
||||
return nil
|
||||
}
|
||||
|
417
vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/gce_loadbalancer_external_test.go
generated
vendored
417
vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/gce_loadbalancer_external_test.go
generated
vendored
@ -18,53 +18,125 @@ package gce
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
computealpha "google.golang.org/api/compute/v0.alpha"
|
||||
compute "google.golang.org/api/compute/v1"
|
||||
|
||||
"k8s.io/api/core/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/types"
|
||||
"k8s.io/kubernetes/pkg/cloudprovider"
|
||||
"k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud"
|
||||
"k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud/mock"
|
||||
kubeletapis "k8s.io/kubernetes/pkg/kubelet/apis"
|
||||
)
|
||||
|
||||
const (
|
||||
projectID = "test-project"
|
||||
region = "us-central1"
|
||||
zoneName = "us-central1-b"
|
||||
nodeName = "test-node-1"
|
||||
clusterName = "Test Cluster Name"
|
||||
clusterID = "test-cluster-id"
|
||||
serviceName = ""
|
||||
)
|
||||
|
||||
var apiService = &v1.Service{
|
||||
Spec: v1.ServiceSpec{
|
||||
SessionAffinity: v1.ServiceAffinityClientIP,
|
||||
Type: v1.ServiceTypeClusterIP,
|
||||
Ports: []v1.ServicePort{{Protocol: v1.ProtocolTCP, Port: int32(123)}},
|
||||
},
|
||||
}
|
||||
|
||||
type fakeRoundTripper struct{}
|
||||
|
||||
func (*fakeRoundTripper) RoundTrip(*http.Request) (*http.Response, error) {
|
||||
return nil, fmt.Errorf("err: test used fake http client")
|
||||
}
|
||||
|
||||
func fakeGCECloud() (*GCECloud, error) {
|
||||
c := &http.Client{Transport: &fakeRoundTripper{}}
|
||||
|
||||
service, err := compute.New(c)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Used in disk unit tests
|
||||
fakeManager := newFakeManager(projectID, region)
|
||||
zonesWithNodes := createNodeZones([]string{zoneName})
|
||||
|
||||
alphaFeatureGate, err := NewAlphaFeatureGate([]string{})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
gce := &GCECloud{
|
||||
region: region,
|
||||
service: service,
|
||||
manager: fakeManager,
|
||||
managedZones: []string{zoneName},
|
||||
projectID: projectID,
|
||||
networkProjectID: projectID,
|
||||
AlphaFeatureGate: alphaFeatureGate,
|
||||
nodeZones: zonesWithNodes,
|
||||
nodeInformerSynced: func() bool { return true },
|
||||
}
|
||||
|
||||
cloud := cloud.NewMockGCE(&gceProjectRouter{gce})
|
||||
cloud.MockTargetPools.AddInstanceHook = mock.AddInstanceHook
|
||||
cloud.MockTargetPools.RemoveInstanceHook = mock.RemoveInstanceHook
|
||||
cloud.MockForwardingRules.InsertHook = mock.InsertFwdRuleHook
|
||||
cloud.MockAddresses.InsertHook = mock.InsertAddressHook
|
||||
cloud.MockAlphaAddresses.InsertHook = mock.InsertAlphaAddressHook
|
||||
|
||||
gce.c = cloud
|
||||
|
||||
return gce, nil
|
||||
}
|
||||
|
||||
func TestEnsureStaticIP(t *testing.T) {
|
||||
fcas := NewFakeCloudAddressService()
|
||||
gce, err := fakeGCECloud()
|
||||
require.NoError(t, err)
|
||||
|
||||
ipName := "some-static-ip"
|
||||
serviceName := ""
|
||||
region := "us-central1"
|
||||
|
||||
// First ensure call
|
||||
ip, existed, err := ensureStaticIP(fcas, ipName, serviceName, region, "", NetworkTierDefault)
|
||||
if err != nil || existed || ip == "" {
|
||||
t.Fatalf(`ensureStaticIP(%v, %v, %v, %v, "") = %v, %v, %v; want valid ip, false, nil`, fcas, ipName, serviceName, region, ip, existed, err)
|
||||
ip, existed, err := ensureStaticIP(gce, ipName, serviceName, region, "", cloud.NetworkTierDefault)
|
||||
if err != nil || existed {
|
||||
t.Fatalf(`ensureStaticIP(%v, %v, %v, %v, "") = %v, %v, %v; want valid ip, false, nil`, gce, ipName, serviceName, region, ip, existed, err)
|
||||
}
|
||||
|
||||
// Second ensure call
|
||||
var ipPrime string
|
||||
ipPrime, existed, err = ensureStaticIP(fcas, ipName, serviceName, region, ip, NetworkTierDefault)
|
||||
ipPrime, existed, err = ensureStaticIP(gce, ipName, serviceName, region, ip, cloud.NetworkTierDefault)
|
||||
if err != nil || !existed || ip != ipPrime {
|
||||
t.Fatalf(`ensureStaticIP(%v, %v, %v, %v, %v) = %v, %v, %v; want %v, true, nil`, fcas, ipName, serviceName, region, ip, ipPrime, existed, err, ip)
|
||||
t.Fatalf(`ensureStaticIP(%v, %v, %v, %v, %v) = %v, %v, %v; want %v, true, nil`, gce, ipName, serviceName, region, ip, ipPrime, existed, err, ip)
|
||||
}
|
||||
}
|
||||
|
||||
func TestEnsureStaticIPWithTier(t *testing.T) {
|
||||
s := NewFakeCloudAddressService()
|
||||
serviceName := ""
|
||||
region := "us-east1"
|
||||
s, err := fakeGCECloud()
|
||||
require.NoError(t, err)
|
||||
|
||||
for desc, tc := range map[string]struct {
|
||||
name string
|
||||
netTier NetworkTier
|
||||
netTier cloud.NetworkTier
|
||||
expected string
|
||||
}{
|
||||
"Premium (default)": {
|
||||
name: "foo-1",
|
||||
netTier: NetworkTierPremium,
|
||||
netTier: cloud.NetworkTierPremium,
|
||||
expected: "PREMIUM",
|
||||
},
|
||||
"Standard": {
|
||||
name: "foo-2",
|
||||
netTier: NetworkTierStandard,
|
||||
netTier: cloud.NetworkTierStandard,
|
||||
expected: "STANDARD",
|
||||
},
|
||||
} {
|
||||
@ -72,7 +144,7 @@ func TestEnsureStaticIPWithTier(t *testing.T) {
|
||||
ip, existed, err := ensureStaticIP(s, tc.name, serviceName, region, "", tc.netTier)
|
||||
assert.NoError(t, err)
|
||||
assert.False(t, existed)
|
||||
assert.NotEqual(t, "", ip)
|
||||
assert.NotEqual(t, ip, "")
|
||||
// Get the Address from the fake address service and verify that the tier
|
||||
// is set correctly.
|
||||
alphaAddr, err := s.GetAlphaRegionAddress(tc.name, region)
|
||||
@ -83,21 +155,19 @@ func TestEnsureStaticIPWithTier(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestVerifyRequestedIP(t *testing.T) {
|
||||
region := "test-region"
|
||||
lbRef := "test-lb"
|
||||
s := NewFakeCloudAddressService()
|
||||
|
||||
for desc, tc := range map[string]struct {
|
||||
requestedIP string
|
||||
fwdRuleIP string
|
||||
netTier NetworkTier
|
||||
netTier cloud.NetworkTier
|
||||
addrList []*computealpha.Address
|
||||
expectErr bool
|
||||
expectUserOwned bool
|
||||
}{
|
||||
"requested IP exists": {
|
||||
requestedIP: "1.1.1.1",
|
||||
netTier: NetworkTierPremium,
|
||||
netTier: cloud.NetworkTierPremium,
|
||||
addrList: []*computealpha.Address{{Name: "foo", Address: "1.1.1.1", NetworkTier: "PREMIUM"}},
|
||||
expectErr: false,
|
||||
expectUserOwned: true,
|
||||
@ -105,28 +175,33 @@ func TestVerifyRequestedIP(t *testing.T) {
|
||||
"requested IP is not static, but is in use by the fwd rule": {
|
||||
requestedIP: "1.1.1.1",
|
||||
fwdRuleIP: "1.1.1.1",
|
||||
netTier: NetworkTierPremium,
|
||||
netTier: cloud.NetworkTierPremium,
|
||||
expectErr: false,
|
||||
},
|
||||
"requested IP is not static and is not used by the fwd rule": {
|
||||
requestedIP: "1.1.1.1",
|
||||
fwdRuleIP: "2.2.2.2",
|
||||
netTier: NetworkTierPremium,
|
||||
netTier: cloud.NetworkTierPremium,
|
||||
expectErr: true,
|
||||
},
|
||||
"no requested IP": {
|
||||
netTier: NetworkTierPremium,
|
||||
netTier: cloud.NetworkTierPremium,
|
||||
expectErr: false,
|
||||
},
|
||||
"requested IP exists, but network tier does not match": {
|
||||
requestedIP: "1.1.1.1",
|
||||
netTier: NetworkTierStandard,
|
||||
netTier: cloud.NetworkTierStandard,
|
||||
addrList: []*computealpha.Address{{Name: "foo", Address: "1.1.1.1", NetworkTier: "PREMIUM"}},
|
||||
expectErr: true,
|
||||
},
|
||||
} {
|
||||
t.Run(desc, func(t *testing.T) {
|
||||
s.SetRegionalAddresses(region, tc.addrList)
|
||||
s, err := fakeGCECloud()
|
||||
require.NoError(t, err)
|
||||
|
||||
for _, addr := range tc.addrList {
|
||||
s.ReserveAlphaRegionAddress(addr, region)
|
||||
}
|
||||
isUserOwnedIP, err := verifyUserRequestedIP(s, region, tc.requestedIP, tc.fwdRuleIP, lbRef, tc.netTier)
|
||||
assert.Equal(t, tc.expectErr, err != nil, fmt.Sprintf("err: %v", err))
|
||||
assert.Equal(t, tc.expectUserOwned, isUserOwnedIP)
|
||||
@ -135,19 +210,18 @@ func TestVerifyRequestedIP(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestCreateForwardingRuleWithTier(t *testing.T) {
|
||||
s := NewFakeCloudForwardingRuleService()
|
||||
// Common variables among the tests.
|
||||
ports := []v1.ServicePort{{Name: "foo", Protocol: v1.ProtocolTCP, Port: int32(123)}}
|
||||
region := "test-region"
|
||||
target := "test-target-pool"
|
||||
svcName := "foo-svc"
|
||||
baseLinkUrl := "https://www.googleapis.com/compute/%v/projects/%v/regions/%v/forwardingRules/%v"
|
||||
|
||||
for desc, tc := range map[string]struct {
|
||||
netTier NetworkTier
|
||||
netTier cloud.NetworkTier
|
||||
expectedRule *computealpha.ForwardingRule
|
||||
}{
|
||||
"Premium tier": {
|
||||
netTier: NetworkTierPremium,
|
||||
netTier: cloud.NetworkTierPremium,
|
||||
expectedRule: &computealpha.ForwardingRule{
|
||||
Name: "lb-1",
|
||||
Description: `{"kubernetes.io/service-name":"foo-svc"}`,
|
||||
@ -156,10 +230,11 @@ func TestCreateForwardingRuleWithTier(t *testing.T) {
|
||||
PortRange: "123-123",
|
||||
Target: target,
|
||||
NetworkTier: "PREMIUM",
|
||||
SelfLink: fmt.Sprintf(baseLinkUrl, "v1", projectID, region, "lb-1"),
|
||||
},
|
||||
},
|
||||
"Standard tier": {
|
||||
netTier: NetworkTierStandard,
|
||||
netTier: cloud.NetworkTierStandard,
|
||||
expectedRule: &computealpha.ForwardingRule{
|
||||
Name: "lb-2",
|
||||
Description: `{"kubernetes.io/service-name":"foo-svc"}`,
|
||||
@ -168,14 +243,18 @@ func TestCreateForwardingRuleWithTier(t *testing.T) {
|
||||
PortRange: "123-123",
|
||||
Target: target,
|
||||
NetworkTier: "STANDARD",
|
||||
SelfLink: fmt.Sprintf(baseLinkUrl, "alpha", projectID, region, "lb-2"),
|
||||
},
|
||||
},
|
||||
} {
|
||||
t.Run(desc, func(t *testing.T) {
|
||||
s, err := fakeGCECloud()
|
||||
require.NoError(t, err)
|
||||
|
||||
lbName := tc.expectedRule.Name
|
||||
ipAddr := tc.expectedRule.IPAddress
|
||||
|
||||
err := createForwardingRule(s, lbName, svcName, region, ipAddr, target, ports, tc.netTier)
|
||||
err = createForwardingRule(s, lbName, svcName, region, ipAddr, target, ports, tc.netTier)
|
||||
assert.NoError(t, err)
|
||||
|
||||
alphaRule, err := s.GetAlphaRegionForwardingRule(lbName, region)
|
||||
@ -186,43 +265,50 @@ func TestCreateForwardingRuleWithTier(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestDeleteAddressWithWrongTier(t *testing.T) {
|
||||
region := "test-region"
|
||||
lbRef := "test-lb"
|
||||
s := NewFakeCloudAddressService()
|
||||
|
||||
s, err := fakeGCECloud()
|
||||
require.NoError(t, err)
|
||||
|
||||
// Enable the cloud.NetworkTiers feature
|
||||
s.AlphaFeatureGate.features[AlphaFeatureNetworkTiers] = true
|
||||
|
||||
for desc, tc := range map[string]struct {
|
||||
addrName string
|
||||
netTier NetworkTier
|
||||
netTier cloud.NetworkTier
|
||||
addrList []*computealpha.Address
|
||||
expectDelete bool
|
||||
}{
|
||||
"Network tiers (premium) match; do nothing": {
|
||||
addrName: "foo1",
|
||||
netTier: NetworkTierPremium,
|
||||
netTier: cloud.NetworkTierPremium,
|
||||
addrList: []*computealpha.Address{{Name: "foo1", Address: "1.1.1.1", NetworkTier: "PREMIUM"}},
|
||||
},
|
||||
"Network tiers (standard) match; do nothing": {
|
||||
addrName: "foo2",
|
||||
netTier: NetworkTierStandard,
|
||||
netTier: cloud.NetworkTierStandard,
|
||||
addrList: []*computealpha.Address{{Name: "foo2", Address: "1.1.1.2", NetworkTier: "STANDARD"}},
|
||||
},
|
||||
"Wrong network tier (standard); delete address": {
|
||||
addrName: "foo3",
|
||||
netTier: NetworkTierPremium,
|
||||
netTier: cloud.NetworkTierPremium,
|
||||
addrList: []*computealpha.Address{{Name: "foo3", Address: "1.1.1.3", NetworkTier: "STANDARD"}},
|
||||
expectDelete: true,
|
||||
},
|
||||
"Wrong network tier (preimium); delete address": {
|
||||
"Wrong network tier (premium); delete address": {
|
||||
addrName: "foo4",
|
||||
netTier: NetworkTierStandard,
|
||||
netTier: cloud.NetworkTierStandard,
|
||||
addrList: []*computealpha.Address{{Name: "foo4", Address: "1.1.1.4", NetworkTier: "PREMIUM"}},
|
||||
expectDelete: true,
|
||||
},
|
||||
} {
|
||||
t.Run(desc, func(t *testing.T) {
|
||||
s.SetRegionalAddresses(region, tc.addrList)
|
||||
for _, addr := range tc.addrList {
|
||||
s.ReserveAlphaRegionAddress(addr, region)
|
||||
}
|
||||
|
||||
// Sanity check to ensure we inject the right address.
|
||||
_, err := s.GetRegionAddress(tc.addrName, region)
|
||||
_, err = s.GetRegionAddress(tc.addrName, region)
|
||||
require.NoError(t, err)
|
||||
|
||||
err = deleteAddressWithWrongTier(s, region, tc.addrName, lbRef, tc.netTier)
|
||||
@ -237,3 +323,254 @@ func TestDeleteAddressWithWrongTier(t *testing.T) {
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func createAndInsertNodes(gce *GCECloud, nodeNames []string) ([]*v1.Node, error) {
|
||||
nodes := []*v1.Node{}
|
||||
|
||||
for _, name := range nodeNames {
|
||||
// Inserting the same node name twice causes an error - here we check if
|
||||
// the instance exists already before insertion.
|
||||
// TestUpdateExternalLoadBalancer inserts a new node, and relies on an older
|
||||
// node to already have been inserted.
|
||||
instance, _ := gce.getInstanceByName(name)
|
||||
|
||||
if instance == nil {
|
||||
err := gce.InsertInstance(
|
||||
projectID,
|
||||
zoneName,
|
||||
&compute.Instance{
|
||||
Name: name,
|
||||
Tags: &compute.Tags{
|
||||
Items: []string{name},
|
||||
},
|
||||
},
|
||||
)
|
||||
if err != nil {
|
||||
return nodes, err
|
||||
}
|
||||
}
|
||||
|
||||
nodes = append(
|
||||
nodes,
|
||||
&v1.Node{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: name,
|
||||
Labels: map[string]string{
|
||||
kubeletapis.LabelHostname: name,
|
||||
},
|
||||
},
|
||||
Status: v1.NodeStatus{
|
||||
NodeInfo: v1.NodeSystemInfo{
|
||||
KubeProxyVersion: "v1.7.2",
|
||||
},
|
||||
},
|
||||
},
|
||||
)
|
||||
|
||||
}
|
||||
|
||||
return nodes, nil
|
||||
}
|
||||
|
||||
func createExternalLoadBalancer(gce *GCECloud) (*v1.LoadBalancerStatus, error) {
|
||||
nodes, err := createAndInsertNodes(gce, []string{nodeName})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return gce.ensureExternalLoadBalancer(
|
||||
clusterName,
|
||||
clusterID,
|
||||
apiService,
|
||||
nil,
|
||||
nodes,
|
||||
)
|
||||
}
|
||||
|
||||
func TestEnsureExternalLoadBalancer(t *testing.T) {
|
||||
gce, err := fakeGCECloud()
|
||||
require.NoError(t, err)
|
||||
|
||||
status, err := createExternalLoadBalancer(gce)
|
||||
assert.NoError(t, err)
|
||||
assert.NotEmpty(t, status.Ingress)
|
||||
|
||||
lbName := cloudprovider.GetLoadBalancerName(apiService)
|
||||
hcName := MakeNodesHealthCheckName(clusterID)
|
||||
|
||||
// Check that Firewalls are created for the LoadBalancer and the HealthCheck
|
||||
fwNames := []string{
|
||||
MakeFirewallName(lbName),
|
||||
MakeHealthCheckFirewallName(clusterID, hcName, true),
|
||||
}
|
||||
|
||||
for _, fwName := range fwNames {
|
||||
firewall, err := gce.GetFirewall(fwName)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, []string{nodeName}, firewall.TargetTags)
|
||||
assert.NotEmpty(t, firewall.SourceRanges)
|
||||
}
|
||||
|
||||
// Check that TargetPool is Created
|
||||
pool, err := gce.GetTargetPool(lbName, region)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, lbName, pool.Name)
|
||||
assert.NotEmpty(t, pool.HealthChecks)
|
||||
assert.Equal(t, 1, len(pool.Instances))
|
||||
|
||||
// Check that HealthCheck is created
|
||||
healthcheck, err := gce.GetHttpHealthCheck(hcName)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, hcName, healthcheck.Name)
|
||||
|
||||
// Check that ForwardingRule is created
|
||||
fwdRule, err := gce.GetRegionForwardingRule(lbName, region)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, lbName, fwdRule.Name)
|
||||
assert.Equal(t, "TCP", fwdRule.IPProtocol)
|
||||
assert.Equal(t, "123-123", fwdRule.PortRange)
|
||||
}
|
||||
|
||||
func TestUpdateExternalLoadBalancer(t *testing.T) {
|
||||
gce, err := fakeGCECloud()
|
||||
require.NoError(t, err)
|
||||
|
||||
_, err = createExternalLoadBalancer(gce)
|
||||
assert.NoError(t, err)
|
||||
|
||||
newNodeName := "test-node-2"
|
||||
newNodes, err := createAndInsertNodes(gce, []string{nodeName, newNodeName})
|
||||
assert.NoError(t, err)
|
||||
|
||||
// Add the new node, then check that it is properly added to the TargetPool
|
||||
err = gce.updateExternalLoadBalancer(clusterName, apiService, newNodes)
|
||||
assert.NoError(t, err)
|
||||
|
||||
lbName := cloudprovider.GetLoadBalancerName(apiService)
|
||||
|
||||
pool, err := gce.GetTargetPool(lbName, region)
|
||||
require.NoError(t, err)
|
||||
|
||||
// TODO: when testify is updated to v1.2.0+, use ElementsMatch instead
|
||||
assert.Contains(
|
||||
t,
|
||||
pool.Instances,
|
||||
fmt.Sprintf("/zones/%s/instances/%s", zoneName, nodeName),
|
||||
)
|
||||
|
||||
assert.Contains(
|
||||
t,
|
||||
pool.Instances,
|
||||
fmt.Sprintf("/zones/%s/instances/%s", zoneName, newNodeName),
|
||||
)
|
||||
|
||||
newNodes, err = createAndInsertNodes(gce, []string{nodeName})
|
||||
assert.NoError(t, err)
|
||||
|
||||
// Remove the new node by calling updateExternalLoadBalancer with a list
|
||||
// only containing the old node, and test that the TargetPool no longer
|
||||
// contains the new node.
|
||||
err = gce.updateExternalLoadBalancer(clusterName, apiService, newNodes)
|
||||
assert.NoError(t, err)
|
||||
|
||||
pool, err = gce.GetTargetPool(lbName, region)
|
||||
require.NoError(t, err)
|
||||
|
||||
assert.Equal(
|
||||
t,
|
||||
[]string{fmt.Sprintf("/zones/%s/instances/%s", zoneName, nodeName)},
|
||||
pool.Instances,
|
||||
)
|
||||
}
|
||||
|
||||
func TestEnsureExternalLoadBalancerDeleted(t *testing.T) {
|
||||
gce, err := fakeGCECloud()
|
||||
require.NoError(t, err)
|
||||
|
||||
_, err = createExternalLoadBalancer(gce)
|
||||
assert.NoError(t, err)
|
||||
|
||||
err = gce.ensureExternalLoadBalancerDeleted(clusterName, clusterID, apiService)
|
||||
assert.NoError(t, err)
|
||||
|
||||
lbName := cloudprovider.GetLoadBalancerName(apiService)
|
||||
hcName := MakeNodesHealthCheckName(clusterID)
|
||||
|
||||
// Check that Firewalls are deleted for the LoadBalancer and the HealthCheck
|
||||
fwNames := []string{
|
||||
MakeFirewallName(lbName),
|
||||
MakeHealthCheckFirewallName(clusterID, hcName, true),
|
||||
}
|
||||
|
||||
for _, fwName := range fwNames {
|
||||
firewall, err := gce.GetFirewall(fwName)
|
||||
require.Error(t, err)
|
||||
assert.Nil(t, firewall)
|
||||
}
|
||||
|
||||
// Check that TargetPool is deleted
|
||||
pool, err := gce.GetTargetPool(lbName, region)
|
||||
require.Error(t, err)
|
||||
assert.Nil(t, pool)
|
||||
|
||||
// Check that HealthCheck is deleted
|
||||
healthcheck, err := gce.GetHttpHealthCheck(hcName)
|
||||
require.Error(t, err)
|
||||
assert.Nil(t, healthcheck)
|
||||
|
||||
// Check forwarding rule is deleted
|
||||
fwdRule, err := gce.GetRegionForwardingRule(lbName, region)
|
||||
require.Error(t, err)
|
||||
assert.Nil(t, fwdRule)
|
||||
}
|
||||
|
||||
func TestLoadBalancerWrongTierResourceDeletion(t *testing.T) {
|
||||
gce, err := fakeGCECloud()
|
||||
require.NoError(t, err)
|
||||
|
||||
// Enable the cloud.NetworkTiers feature
|
||||
gce.AlphaFeatureGate.features[AlphaFeatureNetworkTiers] = true
|
||||
apiService.Annotations = map[string]string{NetworkTierAnnotationKey: "Premium"}
|
||||
|
||||
// cloud.NetworkTier defaults to Premium
|
||||
desiredTier, err := gce.getServiceNetworkTier(apiService)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, cloud.NetworkTierPremium, desiredTier)
|
||||
|
||||
lbName := cloudprovider.GetLoadBalancerName(apiService)
|
||||
serviceName := types.NamespacedName{Namespace: apiService.Namespace, Name: apiService.Name}
|
||||
|
||||
// create ForwardingRule and Address with the wrong tier
|
||||
err = createForwardingRule(
|
||||
gce,
|
||||
lbName,
|
||||
serviceName.String(),
|
||||
region,
|
||||
"",
|
||||
gce.targetPoolURL(lbName),
|
||||
apiService.Spec.Ports,
|
||||
cloud.NetworkTierStandard,
|
||||
)
|
||||
require.NoError(t, err)
|
||||
|
||||
addressObj := &computealpha.Address{
|
||||
Name: lbName,
|
||||
Description: serviceName.String(),
|
||||
NetworkTier: cloud.NetworkTierStandard.ToGCEValue(),
|
||||
}
|
||||
|
||||
err = gce.ReserveAlphaRegionAddress(addressObj, region)
|
||||
require.NoError(t, err)
|
||||
|
||||
_, err = createExternalLoadBalancer(gce)
|
||||
require.NoError(t, err)
|
||||
|
||||
// Expect forwarding rule tier to not be Standard
|
||||
tier, err := gce.getNetworkTierFromForwardingRule(lbName, region)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, cloud.NetworkTierDefault.ToGCEValue(), tier)
|
||||
|
||||
// Expect address to be deleted
|
||||
_, err = gce.GetRegionAddress(lbName, region)
|
||||
assert.True(t, isNotFound(err))
|
||||
}
|
||||
|
33
vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/gce_loadbalancer_internal.go
generated
vendored
33
vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/gce_loadbalancer_internal.go
generated
vendored
@ -28,6 +28,7 @@ import (
|
||||
"k8s.io/apimachinery/pkg/util/sets"
|
||||
v1_service "k8s.io/kubernetes/pkg/api/v1/service"
|
||||
"k8s.io/kubernetes/pkg/cloudprovider"
|
||||
"k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud"
|
||||
)
|
||||
|
||||
const (
|
||||
@ -37,7 +38,7 @@ const (
|
||||
func (gce *GCECloud) ensureInternalLoadBalancer(clusterName, clusterID string, svc *v1.Service, existingFwdRule *compute.ForwardingRule, nodes []*v1.Node) (*v1.LoadBalancerStatus, error) {
|
||||
nm := types.NamespacedName{Name: svc.Name, Namespace: svc.Namespace}
|
||||
ports, protocol := getPortsAndProtocol(svc.Spec.Ports)
|
||||
scheme := schemeInternal
|
||||
scheme := cloud.SchemeInternal
|
||||
loadBalancerName := cloudprovider.GetLoadBalancerName(svc)
|
||||
sharedBackend := shareBackendService(svc)
|
||||
backendServiceName := makeBackendServiceName(loadBalancerName, clusterID, sharedBackend, scheme, protocol, svc.Spec.SessionAffinity)
|
||||
@ -82,10 +83,18 @@ func (gce *GCECloud) ensureInternalLoadBalancer(clusterName, clusterID string, s
|
||||
requestedIP := determineRequestedIP(svc, existingFwdRule)
|
||||
ipToUse := requestedIP
|
||||
|
||||
// If the ILB already exists, continue using the subnet that it's already using.
|
||||
// This is to support existing ILBs that were setup using the wrong subnet.
|
||||
subnetworkURL := gce.SubnetworkURL()
|
||||
if existingFwdRule != nil && existingFwdRule.Subnetwork != "" {
|
||||
// external LBs have an empty Subnetwork field.
|
||||
subnetworkURL = existingFwdRule.Subnetwork
|
||||
}
|
||||
|
||||
var addrMgr *addressManager
|
||||
// If the network is not a legacy network, use the address manager
|
||||
if !gce.IsLegacyNetwork() {
|
||||
addrMgr = newAddressManager(gce, nm.String(), gce.Region(), gce.SubnetworkURL(), loadBalancerName, requestedIP, schemeInternal)
|
||||
addrMgr = newAddressManager(gce, nm.String(), gce.Region(), subnetworkURL, loadBalancerName, requestedIP, cloud.SchemeInternal)
|
||||
ipToUse, err = addrMgr.HoldAddress()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@ -108,9 +117,10 @@ func (gce *GCECloud) ensureInternalLoadBalancer(clusterName, clusterID string, s
|
||||
LoadBalancingScheme: string(scheme),
|
||||
}
|
||||
|
||||
// Specify subnetwork if known
|
||||
if len(gce.subnetworkURL) > 0 {
|
||||
expectedFwdRule.Subnetwork = gce.subnetworkURL
|
||||
// Given that CreateGCECloud will attempt to determine the subnet based off the network,
|
||||
// the subnetwork should rarely be unknown.
|
||||
if subnetworkURL != "" {
|
||||
expectedFwdRule.Subnetwork = subnetworkURL
|
||||
} else {
|
||||
expectedFwdRule.Network = gce.networkURL
|
||||
}
|
||||
@ -199,7 +209,7 @@ func (gce *GCECloud) updateInternalLoadBalancer(clusterName, clusterID string, s
|
||||
|
||||
// Generate the backend service name
|
||||
_, protocol := getPortsAndProtocol(svc.Spec.Ports)
|
||||
scheme := schemeInternal
|
||||
scheme := cloud.SchemeInternal
|
||||
loadBalancerName := cloudprovider.GetLoadBalancerName(svc)
|
||||
backendServiceName := makeBackendServiceName(loadBalancerName, clusterID, shareBackendService(svc), scheme, protocol, svc.Spec.SessionAffinity)
|
||||
// Ensure the backend service has the proper backend/instance-group links
|
||||
@ -209,7 +219,7 @@ func (gce *GCECloud) updateInternalLoadBalancer(clusterName, clusterID string, s
|
||||
func (gce *GCECloud) ensureInternalLoadBalancerDeleted(clusterName, clusterID string, svc *v1.Service) error {
|
||||
loadBalancerName := cloudprovider.GetLoadBalancerName(svc)
|
||||
_, protocol := getPortsAndProtocol(svc.Spec.Ports)
|
||||
scheme := schemeInternal
|
||||
scheme := cloud.SchemeInternal
|
||||
sharedBackend := shareBackendService(svc)
|
||||
sharedHealthCheck := !v1_service.RequestsOnlyLocalTraffic(svc)
|
||||
|
||||
@ -435,7 +445,7 @@ func (gce *GCECloud) ensureInternalInstanceGroup(name, zone string, nodes []*v1.
|
||||
return "", err
|
||||
}
|
||||
|
||||
for _, ins := range instances.Items {
|
||||
for _, ins := range instances {
|
||||
parts := strings.Split(ins.Instance, "/")
|
||||
gceNodes.Insert(parts[len(parts)-1])
|
||||
}
|
||||
@ -497,7 +507,7 @@ func (gce *GCECloud) ensureInternalInstanceGroupsDeleted(name string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (gce *GCECloud) ensureInternalBackendService(name, description string, affinityType v1.ServiceAffinity, scheme lbScheme, protocol v1.Protocol, igLinks []string, hcLink string) error {
|
||||
func (gce *GCECloud) ensureInternalBackendService(name, description string, affinityType v1.ServiceAffinity, scheme cloud.LbScheme, protocol v1.Protocol, igLinks []string, hcLink string) error {
|
||||
glog.V(2).Infof("ensureInternalBackendService(%v, %v, %v): checking existing backend service with %d groups", name, scheme, protocol, len(igLinks))
|
||||
bs, err := gce.GetRegionBackendService(name, gce.region)
|
||||
if err != nil && !isNotFound(err) {
|
||||
@ -525,11 +535,6 @@ func (gce *GCECloud) ensureInternalBackendService(name, description string, affi
|
||||
glog.V(2).Infof("ensureInternalBackendService: created backend service %v successfully", name)
|
||||
return nil
|
||||
}
|
||||
// Check existing backend service
|
||||
existingIGLinks := sets.NewString()
|
||||
for _, be := range bs.Backends {
|
||||
existingIGLinks.Insert(be.Group)
|
||||
}
|
||||
|
||||
if backendSvcEqual(expectedBS, bs) {
|
||||
return nil
|
||||
|
3
vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/gce_loadbalancer_naming.go
generated
vendored
3
vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/gce_loadbalancer_naming.go
generated
vendored
@ -24,6 +24,7 @@ import (
|
||||
|
||||
"k8s.io/api/core/v1"
|
||||
"k8s.io/apimachinery/pkg/types"
|
||||
"k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud"
|
||||
)
|
||||
|
||||
// Internal Load Balancer
|
||||
@ -33,7 +34,7 @@ func makeInstanceGroupName(clusterID string) string {
|
||||
return fmt.Sprintf("k8s-ig--%s", clusterID)
|
||||
}
|
||||
|
||||
func makeBackendServiceName(loadBalancerName, clusterID string, shared bool, scheme lbScheme, protocol v1.Protocol, svcAffinity v1.ServiceAffinity) string {
|
||||
func makeBackendServiceName(loadBalancerName, clusterID string, shared bool, scheme cloud.LbScheme, protocol v1.Protocol, svcAffinity v1.ServiceAffinity) string {
|
||||
if shared {
|
||||
hash := sha1.New()
|
||||
|
||||
|
119
vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/gce_networkendpointgroup.go
generated
vendored
119
vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/gce_networkendpointgroup.go
generated
vendored
@ -18,8 +18,13 @@ package gce
|
||||
|
||||
import (
|
||||
"context"
|
||||
computealpha "google.golang.org/api/compute/v0.alpha"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
computealpha "google.golang.org/api/compute/v0.alpha"
|
||||
|
||||
"k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud/filter"
|
||||
"k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud/meta"
|
||||
)
|
||||
|
||||
const (
|
||||
@ -32,48 +37,45 @@ func newNetworkEndpointGroupMetricContext(request string, zone string) *metricCo
|
||||
}
|
||||
|
||||
func (gce *GCECloud) GetNetworkEndpointGroup(name string, zone string) (*computealpha.NetworkEndpointGroup, error) {
|
||||
if err := gce.alphaFeatureEnabled(AlphaFeatureNetworkEndpointGroup); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
mc := newNetworkEndpointGroupMetricContext("get", zone)
|
||||
v, err := gce.serviceAlpha.NetworkEndpointGroups.Get(gce.ProjectID(), zone, name).Do()
|
||||
if err := gce.alphaFeatureEnabled(AlphaFeatureNetworkEndpointGroup); err != nil {
|
||||
return nil, mc.Observe(err)
|
||||
}
|
||||
v, err := gce.c.AlphaNetworkEndpointGroups().Get(context.Background(), meta.ZonalKey(name, zone))
|
||||
return v, mc.Observe(err)
|
||||
}
|
||||
|
||||
func (gce *GCECloud) ListNetworkEndpointGroup(zone string) ([]*computealpha.NetworkEndpointGroup, error) {
|
||||
if err := gce.alphaFeatureEnabled(AlphaFeatureNetworkEndpointGroup); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
mc := newNetworkEndpointGroupMetricContext("list", zone)
|
||||
networkEndpointGroups := []*computealpha.NetworkEndpointGroup{}
|
||||
err := gce.serviceAlpha.NetworkEndpointGroups.List(gce.ProjectID(), zone).Pages(context.Background(), func(res *computealpha.NetworkEndpointGroupList) error {
|
||||
networkEndpointGroups = append(networkEndpointGroups, res.Items...)
|
||||
return nil
|
||||
})
|
||||
return networkEndpointGroups, mc.Observe(err)
|
||||
if err := gce.alphaFeatureEnabled(AlphaFeatureNetworkEndpointGroup); err != nil {
|
||||
return nil, mc.Observe(err)
|
||||
}
|
||||
negs, err := gce.c.AlphaNetworkEndpointGroups().List(context.Background(), zone, filter.None)
|
||||
return negs, mc.Observe(err)
|
||||
}
|
||||
|
||||
// AggregatedListNetworkEndpointGroup returns a map of zone -> endpoint group.
|
||||
func (gce *GCECloud) AggregatedListNetworkEndpointGroup() (map[string][]*computealpha.NetworkEndpointGroup, error) {
|
||||
if err := gce.alphaFeatureEnabled(AlphaFeatureNetworkEndpointGroup); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
mc := newNetworkEndpointGroupMetricContext("aggregated_list", "")
|
||||
zoneNetworkEndpointGroupMap := map[string][]*computealpha.NetworkEndpointGroup{}
|
||||
err := gce.serviceAlpha.NetworkEndpointGroups.AggregatedList(gce.ProjectID()).Pages(context.Background(), func(res *computealpha.NetworkEndpointGroupAggregatedList) error {
|
||||
for key, negs := range res.Items {
|
||||
if len(negs.NetworkEndpointGroups) == 0 {
|
||||
continue
|
||||
}
|
||||
// key has the format of "zones/${zone_name}"
|
||||
zone := strings.Split(key, "/")[1]
|
||||
if _, ok := zoneNetworkEndpointGroupMap[zone]; !ok {
|
||||
zoneNetworkEndpointGroupMap[zone] = []*computealpha.NetworkEndpointGroup{}
|
||||
}
|
||||
zoneNetworkEndpointGroupMap[zone] = append(zoneNetworkEndpointGroupMap[zone], negs.NetworkEndpointGroups...)
|
||||
if err := gce.alphaFeatureEnabled(AlphaFeatureNetworkEndpointGroup); err != nil {
|
||||
return nil, mc.Observe(err)
|
||||
}
|
||||
// TODO: filter for the region the cluster is in.
|
||||
all, err := gce.c.AlphaNetworkEndpointGroups().AggregatedList(context.Background(), filter.None)
|
||||
if err != nil {
|
||||
return nil, mc.Observe(err)
|
||||
}
|
||||
ret := map[string][]*computealpha.NetworkEndpointGroup{}
|
||||
for key, byZone := range all {
|
||||
// key is "zones/<zone name>"
|
||||
parts := strings.Split(key, "/")
|
||||
if len(parts) != 2 {
|
||||
return nil, mc.Observe(fmt.Errorf("invalid key for AggregatedListNetworkEndpointGroup: %q", key))
|
||||
}
|
||||
return nil
|
||||
})
|
||||
return zoneNetworkEndpointGroupMap, mc.Observe(err)
|
||||
zone := parts[1]
|
||||
ret[zone] = append(ret[zone], byZone...)
|
||||
}
|
||||
return ret, mc.Observe(nil)
|
||||
}
|
||||
|
||||
func (gce *GCECloud) CreateNetworkEndpointGroup(neg *computealpha.NetworkEndpointGroup, zone string) error {
|
||||
@ -81,11 +83,7 @@ func (gce *GCECloud) CreateNetworkEndpointGroup(neg *computealpha.NetworkEndpoin
|
||||
return err
|
||||
}
|
||||
mc := newNetworkEndpointGroupMetricContext("create", zone)
|
||||
op, err := gce.serviceAlpha.NetworkEndpointGroups.Insert(gce.ProjectID(), zone, neg).Do()
|
||||
if err != nil {
|
||||
return mc.Observe(err)
|
||||
}
|
||||
return gce.waitForZoneOp(op, zone, mc)
|
||||
return mc.Observe(gce.c.AlphaNetworkEndpointGroups().Insert(context.Background(), meta.ZonalKey(neg.Name, zone), neg))
|
||||
}
|
||||
|
||||
func (gce *GCECloud) DeleteNetworkEndpointGroup(name string, zone string) error {
|
||||
@ -93,56 +91,43 @@ func (gce *GCECloud) DeleteNetworkEndpointGroup(name string, zone string) error
|
||||
return err
|
||||
}
|
||||
mc := newNetworkEndpointGroupMetricContext("delete", zone)
|
||||
op, err := gce.serviceAlpha.NetworkEndpointGroups.Delete(gce.ProjectID(), zone, name).Do()
|
||||
if err != nil {
|
||||
return mc.Observe(err)
|
||||
}
|
||||
return gce.waitForZoneOp(op, zone, mc)
|
||||
return mc.Observe(gce.c.AlphaNetworkEndpointGroups().Delete(context.Background(), meta.ZonalKey(name, zone)))
|
||||
}
|
||||
|
||||
func (gce *GCECloud) AttachNetworkEndpoints(name, zone string, endpoints []*computealpha.NetworkEndpoint) error {
|
||||
if err := gce.alphaFeatureEnabled(AlphaFeatureNetworkEndpointGroup); err != nil {
|
||||
return err
|
||||
}
|
||||
mc := newNetworkEndpointGroupMetricContext("attach", zone)
|
||||
op, err := gce.serviceAlpha.NetworkEndpointGroups.AttachNetworkEndpoints(gce.ProjectID(), zone, name, &computealpha.NetworkEndpointGroupsAttachEndpointsRequest{
|
||||
NetworkEndpoints: endpoints,
|
||||
}).Do()
|
||||
if err != nil {
|
||||
if err := gce.alphaFeatureEnabled(AlphaFeatureNetworkEndpointGroup); err != nil {
|
||||
return mc.Observe(err)
|
||||
}
|
||||
return gce.waitForZoneOp(op, zone, mc)
|
||||
req := &computealpha.NetworkEndpointGroupsAttachEndpointsRequest{
|
||||
NetworkEndpoints: endpoints,
|
||||
}
|
||||
return mc.Observe(gce.c.AlphaNetworkEndpointGroups().AttachNetworkEndpoints(context.Background(), meta.ZonalKey(name, zone), req))
|
||||
}
|
||||
|
||||
func (gce *GCECloud) DetachNetworkEndpoints(name, zone string, endpoints []*computealpha.NetworkEndpoint) error {
|
||||
if err := gce.alphaFeatureEnabled(AlphaFeatureNetworkEndpointGroup); err != nil {
|
||||
return err
|
||||
}
|
||||
mc := newNetworkEndpointGroupMetricContext("detach", zone)
|
||||
op, err := gce.serviceAlpha.NetworkEndpointGroups.DetachNetworkEndpoints(gce.ProjectID(), zone, name, &computealpha.NetworkEndpointGroupsDetachEndpointsRequest{
|
||||
NetworkEndpoints: endpoints,
|
||||
}).Do()
|
||||
if err != nil {
|
||||
if err := gce.alphaFeatureEnabled(AlphaFeatureNetworkEndpointGroup); err != nil {
|
||||
return mc.Observe(err)
|
||||
}
|
||||
return gce.waitForZoneOp(op, zone, mc)
|
||||
req := &computealpha.NetworkEndpointGroupsDetachEndpointsRequest{
|
||||
NetworkEndpoints: endpoints,
|
||||
}
|
||||
return mc.Observe(gce.c.AlphaNetworkEndpointGroups().DetachNetworkEndpoints(context.Background(), meta.ZonalKey(name, zone), req))
|
||||
}
|
||||
|
||||
func (gce *GCECloud) ListNetworkEndpoints(name, zone string, showHealthStatus bool) ([]*computealpha.NetworkEndpointWithHealthStatus, error) {
|
||||
mc := newNetworkEndpointGroupMetricContext("list_networkendpoints", zone)
|
||||
if err := gce.alphaFeatureEnabled(AlphaFeatureNetworkEndpointGroup); err != nil {
|
||||
return nil, err
|
||||
return nil, mc.Observe(err)
|
||||
}
|
||||
healthStatus := "SKIP"
|
||||
if showHealthStatus {
|
||||
healthStatus = "SHOW"
|
||||
}
|
||||
mc := newNetworkEndpointGroupMetricContext("list_networkendpoints", zone)
|
||||
networkEndpoints := []*computealpha.NetworkEndpointWithHealthStatus{}
|
||||
err := gce.serviceAlpha.NetworkEndpointGroups.ListNetworkEndpoints(gce.ProjectID(), zone, name, &computealpha.NetworkEndpointGroupsListEndpointsRequest{
|
||||
req := &computealpha.NetworkEndpointGroupsListEndpointsRequest{
|
||||
HealthStatus: healthStatus,
|
||||
}).Pages(context.Background(), func(res *computealpha.NetworkEndpointGroupsListNetworkEndpoints) error {
|
||||
networkEndpoints = append(networkEndpoints, res.Items...)
|
||||
return nil
|
||||
})
|
||||
return networkEndpoints, mc.Observe(err)
|
||||
}
|
||||
l, err := gce.c.AlphaNetworkEndpointGroups().ListNetworkEndpoints(context.Background(), meta.ZonalKey(name, zone), req, filter.None)
|
||||
return l, mc.Observe(err)
|
||||
}
|
||||
|
106
vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/gce_routes.go
generated
vendored
106
vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/gce_routes.go
generated
vendored
@ -17,95 +17,75 @@ limitations under the License.
|
||||
package gce
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"path"
|
||||
|
||||
"k8s.io/apimachinery/pkg/types"
|
||||
"k8s.io/kubernetes/pkg/cloudprovider"
|
||||
|
||||
"github.com/golang/glog"
|
||||
compute "google.golang.org/api/compute/v1"
|
||||
"k8s.io/apimachinery/pkg/types"
|
||||
|
||||
"k8s.io/kubernetes/pkg/cloudprovider"
|
||||
"k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud/filter"
|
||||
"k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud/meta"
|
||||
)
|
||||
|
||||
func newRoutesMetricContext(request string) *metricContext {
|
||||
return newGenericMetricContext("routes", request, unusedMetricLabel, unusedMetricLabel, computeV1Version)
|
||||
}
|
||||
|
||||
func (gce *GCECloud) ListRoutes(clusterName string) ([]*cloudprovider.Route, error) {
|
||||
var routes []*cloudprovider.Route
|
||||
pageToken := ""
|
||||
page := 0
|
||||
for ; page == 0 || (pageToken != "" && page < maxPages); page++ {
|
||||
mc := newRoutesMetricContext("list_page")
|
||||
listCall := gce.service.Routes.List(gce.NetworkProjectID())
|
||||
|
||||
prefix := truncateClusterName(clusterName)
|
||||
// Filter for routes starting with clustername AND belonging to the
|
||||
// relevant gcp network AND having description = "k8s-node-route".
|
||||
filter := "(name eq " + prefix + "-.*) "
|
||||
filter = filter + "(network eq " + gce.NetworkURL() + ") "
|
||||
filter = filter + "(description eq " + k8sNodeRouteTag + ")"
|
||||
listCall = listCall.Filter(filter)
|
||||
if pageToken != "" {
|
||||
listCall = listCall.PageToken(pageToken)
|
||||
}
|
||||
res, err := listCall.Do()
|
||||
mc.Observe(err)
|
||||
if err != nil {
|
||||
glog.Errorf("Error getting routes from GCE: %v", err)
|
||||
return nil, err
|
||||
}
|
||||
pageToken = res.NextPageToken
|
||||
for _, r := range res.Items {
|
||||
target := path.Base(r.NextHopInstance)
|
||||
// TODO: Should we lastComponent(target) this?
|
||||
targetNodeName := types.NodeName(target) // NodeName == Instance Name on GCE
|
||||
routes = append(routes, &cloudprovider.Route{Name: r.Name, TargetNode: targetNodeName, DestinationCIDR: r.DestRange})
|
||||
}
|
||||
// ListRoutes in the cloud environment.
|
||||
func (gce *GCECloud) ListRoutes(ctx context.Context, clusterName string) ([]*cloudprovider.Route, error) {
|
||||
mc := newRoutesMetricContext("list")
|
||||
prefix := truncateClusterName(clusterName)
|
||||
f := filter.Regexp("name", prefix+"-.*").AndRegexp("network", gce.NetworkURL()).AndRegexp("description", k8sNodeRouteTag)
|
||||
routes, err := gce.c.Routes().List(context.Background(), f)
|
||||
if err != nil {
|
||||
return nil, mc.Observe(err)
|
||||
}
|
||||
if page >= maxPages {
|
||||
glog.Errorf("ListRoutes exceeded maxPages=%d for Routes.List; truncating.", maxPages)
|
||||
var croutes []*cloudprovider.Route
|
||||
for _, r := range routes {
|
||||
target := path.Base(r.NextHopInstance)
|
||||
// TODO: Should we lastComponent(target) this?
|
||||
targetNodeName := types.NodeName(target) // NodeName == Instance Name on GCE
|
||||
croutes = append(croutes, &cloudprovider.Route{
|
||||
Name: r.Name,
|
||||
TargetNode: targetNodeName,
|
||||
DestinationCIDR: r.DestRange,
|
||||
})
|
||||
}
|
||||
return routes, nil
|
||||
return croutes, mc.Observe(nil)
|
||||
}
|
||||
|
||||
func (gce *GCECloud) CreateRoute(clusterName string, nameHint string, route *cloudprovider.Route) error {
|
||||
routeName := truncateClusterName(clusterName) + "-" + nameHint
|
||||
|
||||
instanceName := mapNodeNameToInstanceName(route.TargetNode)
|
||||
targetInstance, err := gce.getInstanceByName(instanceName)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// CreateRoute in the cloud environment.
|
||||
func (gce *GCECloud) CreateRoute(ctx context.Context, clusterName string, nameHint string, route *cloudprovider.Route) error {
|
||||
mc := newRoutesMetricContext("create")
|
||||
insertOp, err := gce.service.Routes.Insert(gce.NetworkProjectID(), &compute.Route{
|
||||
Name: routeName,
|
||||
|
||||
targetInstance, err := gce.getInstanceByName(mapNodeNameToInstanceName(route.TargetNode))
|
||||
if err != nil {
|
||||
return mc.Observe(err)
|
||||
}
|
||||
cr := &compute.Route{
|
||||
Name: truncateClusterName(clusterName) + "-" + nameHint,
|
||||
DestRange: route.DestinationCIDR,
|
||||
NextHopInstance: fmt.Sprintf("zones/%s/instances/%s", targetInstance.Zone, targetInstance.Name),
|
||||
Network: gce.NetworkURL(),
|
||||
Priority: 1000,
|
||||
Description: k8sNodeRouteTag,
|
||||
}).Do()
|
||||
if err != nil {
|
||||
if isHTTPErrorCode(err, http.StatusConflict) {
|
||||
glog.Infof("Route %v already exists.", routeName)
|
||||
return nil
|
||||
} else {
|
||||
return mc.Observe(err)
|
||||
}
|
||||
}
|
||||
return gce.waitForGlobalOpInProject(insertOp, gce.NetworkProjectID(), mc)
|
||||
err = gce.c.Routes().Insert(context.Background(), meta.GlobalKey(cr.Name), cr)
|
||||
if isHTTPErrorCode(err, http.StatusConflict) {
|
||||
glog.Infof("Route %q already exists.", cr.Name)
|
||||
err = nil
|
||||
}
|
||||
return mc.Observe(err)
|
||||
}
|
||||
|
||||
func (gce *GCECloud) DeleteRoute(clusterName string, route *cloudprovider.Route) error {
|
||||
// DeleteRoute from the cloud environment.
|
||||
func (gce *GCECloud) DeleteRoute(ctx context.Context, clusterName string, route *cloudprovider.Route) error {
|
||||
mc := newRoutesMetricContext("delete")
|
||||
deleteOp, err := gce.service.Routes.Delete(gce.NetworkProjectID(), route.Name).Do()
|
||||
if err != nil {
|
||||
return mc.Observe(err)
|
||||
}
|
||||
return gce.waitForGlobalOpInProject(deleteOp, gce.NetworkProjectID(), mc)
|
||||
return mc.Observe(gce.c.Routes().Delete(context.Background(), meta.GlobalKey(route.Name)))
|
||||
}
|
||||
|
||||
func truncateClusterName(clusterName string) string {
|
||||
|
45
vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/gce_targetpool.go
generated
vendored
45
vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/gce_targetpool.go
generated
vendored
@ -16,7 +16,13 @@ limitations under the License.
|
||||
|
||||
package gce
|
||||
|
||||
import compute "google.golang.org/api/compute/v1"
|
||||
import (
|
||||
"context"
|
||||
|
||||
compute "google.golang.org/api/compute/v1"
|
||||
|
||||
"k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud/meta"
|
||||
)
|
||||
|
||||
func newTargetPoolMetricContext(request, region string) *metricContext {
|
||||
return newGenericMetricContext("targetpool", request, region, unusedMetricLabel, computeV1Version)
|
||||
@ -25,49 +31,36 @@ func newTargetPoolMetricContext(request, region string) *metricContext {
|
||||
// GetTargetPool returns the TargetPool by name.
|
||||
func (gce *GCECloud) GetTargetPool(name, region string) (*compute.TargetPool, error) {
|
||||
mc := newTargetPoolMetricContext("get", region)
|
||||
v, err := gce.service.TargetPools.Get(gce.projectID, region, name).Do()
|
||||
v, err := gce.c.TargetPools().Get(context.Background(), meta.RegionalKey(name, region))
|
||||
return v, mc.Observe(err)
|
||||
}
|
||||
|
||||
// CreateTargetPool creates the passed TargetPool
|
||||
func (gce *GCECloud) CreateTargetPool(tp *compute.TargetPool, region string) error {
|
||||
mc := newTargetPoolMetricContext("create", region)
|
||||
op, err := gce.service.TargetPools.Insert(gce.projectID, region, tp).Do()
|
||||
if err != nil {
|
||||
return mc.Observe(err)
|
||||
}
|
||||
|
||||
return gce.waitForRegionOp(op, region, mc)
|
||||
return mc.Observe(gce.c.TargetPools().Insert(context.Background(), meta.RegionalKey(tp.Name, region), tp))
|
||||
}
|
||||
|
||||
// DeleteTargetPool deletes TargetPool by name.
|
||||
func (gce *GCECloud) DeleteTargetPool(name, region string) error {
|
||||
mc := newTargetPoolMetricContext("delete", region)
|
||||
op, err := gce.service.TargetPools.Delete(gce.projectID, region, name).Do()
|
||||
if err != nil {
|
||||
return mc.Observe(err)
|
||||
}
|
||||
return gce.waitForRegionOp(op, region, mc)
|
||||
return mc.Observe(gce.c.TargetPools().Delete(context.Background(), meta.RegionalKey(name, region)))
|
||||
}
|
||||
|
||||
// AddInstancesToTargetPool adds instances by link to the TargetPool
|
||||
func (gce *GCECloud) AddInstancesToTargetPool(name, region string, instanceRefs []*compute.InstanceReference) error {
|
||||
add := &compute.TargetPoolsAddInstanceRequest{Instances: instanceRefs}
|
||||
mc := newTargetPoolMetricContext("add_instances", region)
|
||||
op, err := gce.service.TargetPools.AddInstance(gce.projectID, region, name, add).Do()
|
||||
if err != nil {
|
||||
return mc.Observe(err)
|
||||
req := &compute.TargetPoolsAddInstanceRequest{
|
||||
Instances: instanceRefs,
|
||||
}
|
||||
return gce.waitForRegionOp(op, region, mc)
|
||||
mc := newTargetPoolMetricContext("add_instances", region)
|
||||
return mc.Observe(gce.c.TargetPools().AddInstance(context.Background(), meta.RegionalKey(name, region), req))
|
||||
}
|
||||
|
||||
// RemoveInstancesToTargetPool removes instances by link to the TargetPool
|
||||
// RemoveInstancesFromTargetPool removes instances by link to the TargetPool
|
||||
func (gce *GCECloud) RemoveInstancesFromTargetPool(name, region string, instanceRefs []*compute.InstanceReference) error {
|
||||
remove := &compute.TargetPoolsRemoveInstanceRequest{Instances: instanceRefs}
|
||||
mc := newTargetPoolMetricContext("remove_instances", region)
|
||||
op, err := gce.service.TargetPools.RemoveInstance(gce.projectID, region, name, remove).Do()
|
||||
if err != nil {
|
||||
return mc.Observe(err)
|
||||
req := &compute.TargetPoolsRemoveInstanceRequest{
|
||||
Instances: instanceRefs,
|
||||
}
|
||||
return gce.waitForRegionOp(op, region, mc)
|
||||
mc := newTargetPoolMetricContext("remove_instances", region)
|
||||
return mc.Observe(gce.c.TargetPools().RemoveInstance(context.Background(), meta.RegionalKey(name, region), req))
|
||||
}
|
||||
|
73
vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/gce_targetproxy.go
generated
vendored
73
vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/gce_targetproxy.go
generated
vendored
@ -17,9 +17,12 @@ limitations under the License.
|
||||
package gce
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"context"
|
||||
|
||||
compute "google.golang.org/api/compute/v1"
|
||||
|
||||
"k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud/filter"
|
||||
"k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud/meta"
|
||||
)
|
||||
|
||||
func newTargetProxyMetricContext(request string) *metricContext {
|
||||
@ -29,49 +32,33 @@ func newTargetProxyMetricContext(request string) *metricContext {
|
||||
// GetTargetHttpProxy returns the UrlMap by name.
|
||||
func (gce *GCECloud) GetTargetHttpProxy(name string) (*compute.TargetHttpProxy, error) {
|
||||
mc := newTargetProxyMetricContext("get")
|
||||
v, err := gce.service.TargetHttpProxies.Get(gce.projectID, name).Do()
|
||||
v, err := gce.c.TargetHttpProxies().Get(context.Background(), meta.GlobalKey(name))
|
||||
return v, mc.Observe(err)
|
||||
}
|
||||
|
||||
// CreateTargetHttpProxy creates a TargetHttpProxy
|
||||
func (gce *GCECloud) CreateTargetHttpProxy(proxy *compute.TargetHttpProxy) error {
|
||||
mc := newTargetProxyMetricContext("create")
|
||||
op, err := gce.service.TargetHttpProxies.Insert(gce.projectID, proxy).Do()
|
||||
if err != nil {
|
||||
return mc.Observe(err)
|
||||
}
|
||||
return gce.waitForGlobalOp(op, mc)
|
||||
return mc.Observe(gce.c.TargetHttpProxies().Insert(context.Background(), meta.GlobalKey(proxy.Name), proxy))
|
||||
}
|
||||
|
||||
// SetUrlMapForTargetHttpProxy sets the given UrlMap for the given TargetHttpProxy.
|
||||
func (gce *GCECloud) SetUrlMapForTargetHttpProxy(proxy *compute.TargetHttpProxy, urlMap *compute.UrlMap) error {
|
||||
ref := &compute.UrlMapReference{UrlMap: urlMap.SelfLink}
|
||||
mc := newTargetProxyMetricContext("set_url_map")
|
||||
op, err := gce.service.TargetHttpProxies.SetUrlMap(
|
||||
gce.projectID, proxy.Name, &compute.UrlMapReference{UrlMap: urlMap.SelfLink}).Do()
|
||||
if err != nil {
|
||||
return mc.Observe(err)
|
||||
}
|
||||
return gce.waitForGlobalOp(op, mc)
|
||||
return mc.Observe(gce.c.TargetHttpProxies().SetUrlMap(context.Background(), meta.GlobalKey(proxy.Name), ref))
|
||||
}
|
||||
|
||||
// DeleteTargetHttpProxy deletes the TargetHttpProxy by name.
|
||||
func (gce *GCECloud) DeleteTargetHttpProxy(name string) error {
|
||||
mc := newTargetProxyMetricContext("delete")
|
||||
op, err := gce.service.TargetHttpProxies.Delete(gce.projectID, name).Do()
|
||||
if err != nil {
|
||||
if isHTTPErrorCode(err, http.StatusNotFound) {
|
||||
return nil
|
||||
}
|
||||
return mc.Observe(err)
|
||||
}
|
||||
return gce.waitForGlobalOp(op, mc)
|
||||
return mc.Observe(gce.c.TargetHttpProxies().Delete(context.Background(), meta.GlobalKey(name)))
|
||||
}
|
||||
|
||||
// ListTargetHttpProxies lists all TargetHttpProxies in the project.
|
||||
func (gce *GCECloud) ListTargetHttpProxies() (*compute.TargetHttpProxyList, error) {
|
||||
func (gce *GCECloud) ListTargetHttpProxies() ([]*compute.TargetHttpProxy, error) {
|
||||
mc := newTargetProxyMetricContext("list")
|
||||
// TODO: use PageToken to list all not just the first 500
|
||||
v, err := gce.service.TargetHttpProxies.List(gce.projectID).Do()
|
||||
v, err := gce.c.TargetHttpProxies().List(context.Background(), filter.None)
|
||||
return v, mc.Observe(err)
|
||||
}
|
||||
|
||||
@ -80,59 +67,41 @@ func (gce *GCECloud) ListTargetHttpProxies() (*compute.TargetHttpProxyList, erro
|
||||
// GetTargetHttpsProxy returns the UrlMap by name.
|
||||
func (gce *GCECloud) GetTargetHttpsProxy(name string) (*compute.TargetHttpsProxy, error) {
|
||||
mc := newTargetProxyMetricContext("get")
|
||||
v, err := gce.service.TargetHttpsProxies.Get(gce.projectID, name).Do()
|
||||
v, err := gce.c.TargetHttpsProxies().Get(context.Background(), meta.GlobalKey(name))
|
||||
return v, mc.Observe(err)
|
||||
}
|
||||
|
||||
// CreateTargetHttpsProxy creates a TargetHttpsProxy
|
||||
func (gce *GCECloud) CreateTargetHttpsProxy(proxy *compute.TargetHttpsProxy) error {
|
||||
mc := newTargetProxyMetricContext("create")
|
||||
op, err := gce.service.TargetHttpsProxies.Insert(gce.projectID, proxy).Do()
|
||||
if err != nil {
|
||||
return mc.Observe(err)
|
||||
}
|
||||
return gce.waitForGlobalOp(op, mc)
|
||||
return mc.Observe(gce.c.TargetHttpsProxies().Insert(context.Background(), meta.GlobalKey(proxy.Name), proxy))
|
||||
}
|
||||
|
||||
// SetUrlMapForTargetHttpsProxy sets the given UrlMap for the given TargetHttpsProxy.
|
||||
func (gce *GCECloud) SetUrlMapForTargetHttpsProxy(proxy *compute.TargetHttpsProxy, urlMap *compute.UrlMap) error {
|
||||
mc := newTargetProxyMetricContext("set_url_map")
|
||||
op, err := gce.service.TargetHttpsProxies.SetUrlMap(
|
||||
gce.projectID, proxy.Name, &compute.UrlMapReference{UrlMap: urlMap.SelfLink}).Do()
|
||||
if err != nil {
|
||||
return mc.Observe(err)
|
||||
}
|
||||
return gce.waitForGlobalOp(op, mc)
|
||||
ref := &compute.UrlMapReference{UrlMap: urlMap.SelfLink}
|
||||
return mc.Observe(gce.c.TargetHttpsProxies().SetUrlMap(context.Background(), meta.GlobalKey(proxy.Name), ref))
|
||||
}
|
||||
|
||||
// SetSslCertificateForTargetHttpsProxy sets the given SslCertificate for the given TargetHttpsProxy.
|
||||
func (gce *GCECloud) SetSslCertificateForTargetHttpsProxy(proxy *compute.TargetHttpsProxy, sslCert *compute.SslCertificate) error {
|
||||
mc := newTargetProxyMetricContext("set_ssl_cert")
|
||||
op, err := gce.service.TargetHttpsProxies.SetSslCertificates(
|
||||
gce.projectID, proxy.Name, &compute.TargetHttpsProxiesSetSslCertificatesRequest{SslCertificates: []string{sslCert.SelfLink}}).Do()
|
||||
if err != nil {
|
||||
return mc.Observe(err)
|
||||
req := &compute.TargetHttpsProxiesSetSslCertificatesRequest{
|
||||
SslCertificates: []string{sslCert.SelfLink},
|
||||
}
|
||||
return gce.waitForGlobalOp(op, mc)
|
||||
return mc.Observe(gce.c.TargetHttpsProxies().SetSslCertificates(context.Background(), meta.GlobalKey(proxy.Name), req))
|
||||
}
|
||||
|
||||
// DeleteTargetHttpsProxy deletes the TargetHttpsProxy by name.
|
||||
func (gce *GCECloud) DeleteTargetHttpsProxy(name string) error {
|
||||
mc := newTargetProxyMetricContext("delete")
|
||||
op, err := gce.service.TargetHttpsProxies.Delete(gce.projectID, name).Do()
|
||||
if err != nil {
|
||||
if isHTTPErrorCode(err, http.StatusNotFound) {
|
||||
return nil
|
||||
}
|
||||
return mc.Observe(err)
|
||||
}
|
||||
return gce.waitForGlobalOp(op, mc)
|
||||
return mc.Observe(gce.c.TargetHttpsProxies().Delete(context.Background(), meta.GlobalKey(name)))
|
||||
}
|
||||
|
||||
// ListTargetHttpsProxies lists all TargetHttpsProxies in the project.
|
||||
func (gce *GCECloud) ListTargetHttpsProxies() (*compute.TargetHttpsProxyList, error) {
|
||||
func (gce *GCECloud) ListTargetHttpsProxies() ([]*compute.TargetHttpsProxy, error) {
|
||||
mc := newTargetProxyMetricContext("list")
|
||||
// TODO: use PageToken to list all not just the first 500
|
||||
v, err := gce.service.TargetHttpsProxies.List(gce.projectID).Do()
|
||||
v, err := gce.c.TargetHttpsProxies().List(context.Background(), filter.None)
|
||||
return v, mc.Observe(err)
|
||||
}
|
||||
|
41
vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/gce_test.go
generated
vendored
41
vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/gce_test.go
generated
vendored
@ -17,6 +17,7 @@ limitations under the License.
|
||||
package gce
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"reflect"
|
||||
"strings"
|
||||
@ -100,7 +101,7 @@ func TestGetRegion(t *testing.T) {
|
||||
if !ok {
|
||||
t.Fatalf("Unexpected missing zones impl")
|
||||
}
|
||||
zone, err := zones.GetZone()
|
||||
zone, err := zones.GetZone(context.TODO())
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error %v", err)
|
||||
}
|
||||
@ -175,42 +176,6 @@ func TestComparingHostURLs(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestScrubDNS(t *testing.T) {
|
||||
tcs := []struct {
|
||||
nameserversIn []string
|
||||
searchesIn []string
|
||||
nameserversOut []string
|
||||
searchesOut []string
|
||||
}{
|
||||
{
|
||||
nameserversIn: []string{"1.2.3.4", "5.6.7.8"},
|
||||
nameserversOut: []string{"1.2.3.4", "5.6.7.8"},
|
||||
},
|
||||
{
|
||||
searchesIn: []string{"c.prj.internal.", "12345678910.google.internal.", "google.internal."},
|
||||
searchesOut: []string{"c.prj.internal.", "google.internal."},
|
||||
},
|
||||
{
|
||||
searchesIn: []string{"c.prj.internal.", "12345678910.google.internal.", "zone.c.prj.internal.", "google.internal."},
|
||||
searchesOut: []string{"c.prj.internal.", "zone.c.prj.internal.", "google.internal."},
|
||||
},
|
||||
{
|
||||
searchesIn: []string{"c.prj.internal.", "12345678910.google.internal.", "zone.c.prj.internal.", "google.internal.", "unexpected"},
|
||||
searchesOut: []string{"c.prj.internal.", "zone.c.prj.internal.", "google.internal.", "unexpected"},
|
||||
},
|
||||
}
|
||||
gce := &GCECloud{}
|
||||
for i := range tcs {
|
||||
n, s := gce.ScrubDNS(tcs[i].nameserversIn, tcs[i].searchesIn)
|
||||
if !reflect.DeepEqual(n, tcs[i].nameserversOut) {
|
||||
t.Errorf("Expected %v, got %v", tcs[i].nameserversOut, n)
|
||||
}
|
||||
if !reflect.DeepEqual(s, tcs[i].searchesOut) {
|
||||
t.Errorf("Expected %v, got %v", tcs[i].searchesOut, s)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestSplitProviderID(t *testing.T) {
|
||||
providers := []struct {
|
||||
providerID string
|
||||
@ -341,7 +306,7 @@ func TestGetZoneByProviderID(t *testing.T) {
|
||||
region: "us-central1",
|
||||
}
|
||||
for _, test := range tests {
|
||||
zone, err := gce.GetZoneByProviderID(test.providerID)
|
||||
zone, err := gce.GetZoneByProviderID(context.TODO(), test.providerID)
|
||||
if (err != nil) != test.fail {
|
||||
t.Errorf("Expected to fail=%t, provider ID %v, tests %s", test.fail, test, test.description)
|
||||
}
|
||||
|
189
vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/gce_tpu.go
generated
vendored
Normal file
189
vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/gce_tpu.go
generated
vendored
Normal file
@ -0,0 +1,189 @@
|
||||
/*
|
||||
Copyright 2018 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 (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"github.com/golang/glog"
|
||||
"google.golang.org/api/googleapi"
|
||||
tpuapi "google.golang.org/api/tpu/v1alpha1"
|
||||
|
||||
"k8s.io/apimachinery/pkg/util/wait"
|
||||
)
|
||||
|
||||
// newTPUService returns a new tpuService using the client to communicate with
|
||||
// the Cloud TPU APIs.
|
||||
func newTPUService(client *http.Client) (*tpuService, error) {
|
||||
s, err := tpuapi.New(client)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &tpuService{
|
||||
nodesService: tpuapi.NewProjectsLocationsNodesService(s),
|
||||
operationsService: tpuapi.NewProjectsLocationsOperationsService(s),
|
||||
}, nil
|
||||
}
|
||||
|
||||
// tpuService encapsulates the TPU services on nodes and the operations on the
|
||||
// nodes.
|
||||
type tpuService struct {
|
||||
nodesService *tpuapi.ProjectsLocationsNodesService
|
||||
operationsService *tpuapi.ProjectsLocationsOperationsService
|
||||
}
|
||||
|
||||
// CreateTPU creates the Cloud TPU node with the specified name in the
|
||||
// specified zone.
|
||||
func (gce *GCECloud) CreateTPU(ctx context.Context, name, zone string, node *tpuapi.Node) (*tpuapi.Node, error) {
|
||||
var err error
|
||||
mc := newTPUMetricContext("create", zone)
|
||||
defer mc.Observe(err)
|
||||
|
||||
var op *tpuapi.Operation
|
||||
parent := getTPUParentName(gce.projectID, zone)
|
||||
op, err = gce.tpuService.nodesService.Create(parent, node).NodeId(name).Do()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
glog.V(2).Infof("Creating Cloud TPU %q in zone %q with operation %q", name, zone, op.Name)
|
||||
|
||||
op, err = gce.waitForTPUOp(30*time.Second, 10*time.Minute, op)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
err = getErrorFromTPUOp(op)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
output := new(tpuapi.Node)
|
||||
err = json.Unmarshal(op.Response, output)
|
||||
if err != nil {
|
||||
err = fmt.Errorf("failed to unmarshal response from operation %q: response = %v, err = %v", op.Name, op.Response, err)
|
||||
return nil, err
|
||||
}
|
||||
return output, nil
|
||||
}
|
||||
|
||||
// DeleteTPU deletes the Cloud TPU with the specified name in the specified
|
||||
// zone.
|
||||
func (gce *GCECloud) DeleteTPU(ctx context.Context, name, zone string) error {
|
||||
var err error
|
||||
mc := newTPUMetricContext("delete", zone)
|
||||
defer mc.Observe(err)
|
||||
|
||||
var op *tpuapi.Operation
|
||||
name = getTPUName(gce.projectID, zone, name)
|
||||
op, err = gce.tpuService.nodesService.Delete(name).Do()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
glog.V(2).Infof("Deleting Cloud TPU %q in zone %q with operation %q", name, zone, op.Name)
|
||||
|
||||
op, err = gce.waitForTPUOp(30*time.Second, 10*time.Minute, op)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = getErrorFromTPUOp(op)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetTPU returns the Cloud TPU with the specified name in the specified zone.
|
||||
func (gce *GCECloud) GetTPU(ctx context.Context, name, zone string) (*tpuapi.Node, error) {
|
||||
mc := newTPUMetricContext("get", zone)
|
||||
|
||||
name = getTPUName(gce.projectID, zone, name)
|
||||
node, err := gce.tpuService.nodesService.Get(name).Do()
|
||||
if err != nil {
|
||||
return nil, mc.Observe(err)
|
||||
}
|
||||
return node, mc.Observe(nil)
|
||||
}
|
||||
|
||||
// ListTPUs returns Cloud TPUs in the specified zone.
|
||||
func (gce *GCECloud) ListTPUs(ctx context.Context, zone string) ([]*tpuapi.Node, error) {
|
||||
mc := newTPUMetricContext("list", zone)
|
||||
|
||||
parent := getTPUParentName(gce.projectID, zone)
|
||||
response, err := gce.tpuService.nodesService.List(parent).Do()
|
||||
if err != nil {
|
||||
return nil, mc.Observe(err)
|
||||
}
|
||||
return response.Nodes, mc.Observe(nil)
|
||||
}
|
||||
|
||||
// waitForTPUOp checks whether the op is done every interval before the timeout
|
||||
// occurs.
|
||||
func (gce *GCECloud) waitForTPUOp(interval, timeout time.Duration, op *tpuapi.Operation) (*tpuapi.Operation, error) {
|
||||
if err := wait.PollImmediate(interval, timeout, func() (bool, error) {
|
||||
glog.V(3).Infof("Waiting for operation %q to complete...", op.Name)
|
||||
|
||||
start := time.Now()
|
||||
gce.operationPollRateLimiter.Accept()
|
||||
duration := time.Now().Sub(start)
|
||||
if duration > 5*time.Second {
|
||||
glog.V(2).Infof("Getting operation %q throttled for %v", op.Name, duration)
|
||||
}
|
||||
|
||||
var err error
|
||||
op, err = gce.tpuService.operationsService.Get(op.Name).Do()
|
||||
if err != nil {
|
||||
return true, err
|
||||
}
|
||||
if op.Done {
|
||||
glog.V(3).Infof("Operation %q has completed", op.Name)
|
||||
return true, nil
|
||||
}
|
||||
return false, nil
|
||||
}); err != nil {
|
||||
return nil, fmt.Errorf("failed to wait for operation %q: %s", op.Name, err)
|
||||
}
|
||||
return op, nil
|
||||
}
|
||||
|
||||
// newTPUMetricContext returns a new metricContext used for recording metrics
|
||||
// of Cloud TPU API calls.
|
||||
func newTPUMetricContext(request, zone string) *metricContext {
|
||||
return newGenericMetricContext("tpus", request, unusedMetricLabel, zone, "alpha")
|
||||
}
|
||||
|
||||
// getErrorFromTPUOp returns the error in the failed op, or nil if the op
|
||||
// succeed.
|
||||
func getErrorFromTPUOp(op *tpuapi.Operation) error {
|
||||
if op != nil && op.Error != nil {
|
||||
return &googleapi.Error{
|
||||
Code: op.ServerResponse.HTTPStatusCode,
|
||||
Message: op.Error.Message,
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func getTPUParentName(project, zone string) string {
|
||||
return fmt.Sprintf("projects/%s/locations/%s", project, zone)
|
||||
}
|
||||
|
||||
func getTPUName(project, zone, name string) string {
|
||||
return fmt.Sprintf("projects/%s/locations/%s/nodes/%s", project, zone, name)
|
||||
}
|
33
vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/gce_urlmap.go
generated
vendored
33
vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/gce_urlmap.go
generated
vendored
@ -17,9 +17,12 @@ limitations under the License.
|
||||
package gce
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"context"
|
||||
|
||||
compute "google.golang.org/api/compute/v1"
|
||||
|
||||
"k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud/filter"
|
||||
"k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud/meta"
|
||||
)
|
||||
|
||||
func newUrlMapMetricContext(request string) *metricContext {
|
||||
@ -29,47 +32,31 @@ func newUrlMapMetricContext(request string) *metricContext {
|
||||
// GetUrlMap returns the UrlMap by name.
|
||||
func (gce *GCECloud) GetUrlMap(name string) (*compute.UrlMap, error) {
|
||||
mc := newUrlMapMetricContext("get")
|
||||
v, err := gce.service.UrlMaps.Get(gce.projectID, name).Do()
|
||||
v, err := gce.c.UrlMaps().Get(context.Background(), meta.GlobalKey(name))
|
||||
return v, mc.Observe(err)
|
||||
}
|
||||
|
||||
// CreateUrlMap creates a url map
|
||||
func (gce *GCECloud) CreateUrlMap(urlMap *compute.UrlMap) error {
|
||||
mc := newUrlMapMetricContext("create")
|
||||
op, err := gce.service.UrlMaps.Insert(gce.projectID, urlMap).Do()
|
||||
if err != nil {
|
||||
return mc.Observe(err)
|
||||
}
|
||||
return gce.waitForGlobalOp(op, mc)
|
||||
return mc.Observe(gce.c.UrlMaps().Insert(context.Background(), meta.GlobalKey(urlMap.Name), urlMap))
|
||||
}
|
||||
|
||||
// UpdateUrlMap applies the given UrlMap as an update
|
||||
func (gce *GCECloud) UpdateUrlMap(urlMap *compute.UrlMap) error {
|
||||
mc := newUrlMapMetricContext("update")
|
||||
op, err := gce.service.UrlMaps.Update(gce.projectID, urlMap.Name, urlMap).Do()
|
||||
if err != nil {
|
||||
return mc.Observe(err)
|
||||
}
|
||||
return gce.waitForGlobalOp(op, mc)
|
||||
return mc.Observe(gce.c.UrlMaps().Update(context.Background(), meta.GlobalKey(urlMap.Name), urlMap))
|
||||
}
|
||||
|
||||
// DeleteUrlMap deletes a url map by name.
|
||||
func (gce *GCECloud) DeleteUrlMap(name string) error {
|
||||
mc := newUrlMapMetricContext("delete")
|
||||
op, err := gce.service.UrlMaps.Delete(gce.projectID, name).Do()
|
||||
if err != nil {
|
||||
if isHTTPErrorCode(err, http.StatusNotFound) {
|
||||
return nil
|
||||
}
|
||||
return mc.Observe(err)
|
||||
}
|
||||
return gce.waitForGlobalOp(op, mc)
|
||||
return mc.Observe(gce.c.UrlMaps().Delete(context.Background(), meta.GlobalKey(name)))
|
||||
}
|
||||
|
||||
// ListUrlMaps lists all UrlMaps in the project.
|
||||
func (gce *GCECloud) ListUrlMaps() (*compute.UrlMapList, error) {
|
||||
func (gce *GCECloud) ListUrlMaps() ([]*compute.UrlMap, error) {
|
||||
mc := newUrlMapMetricContext("list")
|
||||
// TODO: use PageToken to list all not just the first 500
|
||||
v, err := gce.service.UrlMaps.List(gce.projectID).Do()
|
||||
v, err := gce.c.UrlMaps().List(context.Background(), filter.None)
|
||||
return v, mc.Observe(err)
|
||||
}
|
||||
|
9
vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/gce_util.go
generated
vendored
9
vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/gce_util.go
generated
vendored
@ -22,11 +22,13 @@ import (
|
||||
"net"
|
||||
"net/http"
|
||||
"regexp"
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
"k8s.io/api/core/v1"
|
||||
"k8s.io/apimachinery/pkg/types"
|
||||
"k8s.io/apimachinery/pkg/util/sets"
|
||||
"k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud"
|
||||
|
||||
"cloud.google.com/go/compute/metadata"
|
||||
compute "google.golang.org/api/compute/v1"
|
||||
@ -98,8 +100,13 @@ func firewallToGcloudArgs(fw *compute.Firewall, projectID string) string {
|
||||
allPorts = append(allPorts, fmt.Sprintf("%v:%v", a.IPProtocol, p))
|
||||
}
|
||||
}
|
||||
|
||||
// Sort all slices to prevent the event from being duped
|
||||
sort.Strings(allPorts)
|
||||
allow := strings.Join(allPorts, ",")
|
||||
sort.Strings(fw.SourceRanges)
|
||||
srcRngs := strings.Join(fw.SourceRanges, ",")
|
||||
sort.Strings(fw.TargetTags)
|
||||
targets := strings.Join(fw.TargetTags, ",")
|
||||
return fmt.Sprintf("--description %q --allow %v --source-ranges %v --target-tags %v --project %v", fw.Description, allow, srcRngs, targets, projectID)
|
||||
}
|
||||
@ -214,7 +221,7 @@ func handleAlphaNetworkTierGetError(err error) (string, error) {
|
||||
// Network tier is still an Alpha feature in GCP, and not every project
|
||||
// is whitelisted to access the API. If we cannot access the API, just
|
||||
// assume the tier is premium.
|
||||
return NetworkTierDefault.ToGCEValue(), nil
|
||||
return cloud.NetworkTierDefault.ToGCEValue(), nil
|
||||
}
|
||||
// Can't get the network tier, just return an error.
|
||||
return "", err
|
||||
|
24
vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/gce_util_test.go
generated
vendored
24
vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/gce_util_test.go
generated
vendored
@ -88,3 +88,27 @@ func TestSubnetsInCIDR(t *testing.T) {
|
||||
t.Errorf("autoSubnetInList() = %v, expected: %v", gotNames, expectedNames)
|
||||
}
|
||||
}
|
||||
|
||||
func TestFirewallToGcloudArgs(t *testing.T) {
|
||||
firewall := compute.Firewall{
|
||||
Description: "Last Line of Defense",
|
||||
TargetTags: []string{"jock-nodes", "band-nodes"},
|
||||
SourceRanges: []string{"3.3.3.3/20", "1.1.1.1/20", "2.2.2.2/20"},
|
||||
Allowed: []*compute.FirewallAllowed{
|
||||
{
|
||||
IPProtocol: "udp",
|
||||
Ports: []string{"321", "123-456", "123"},
|
||||
},
|
||||
{
|
||||
IPProtocol: "tcp",
|
||||
Ports: []string{"321", "123-456", "123"},
|
||||
},
|
||||
},
|
||||
}
|
||||
got := firewallToGcloudArgs(&firewall, "my-project")
|
||||
|
||||
var e = `--description "Last Line of Defense" --allow tcp:123,tcp:123-456,tcp:321,udp:123,udp:123-456,udp:321 --source-ranges 1.1.1.1/20,2.2.2.2/20,3.3.3.3/20 --target-tags band-nodes,jock-nodes --project my-project`
|
||||
if got != e {
|
||||
t.Errorf("%q does not equal %q", got, e)
|
||||
}
|
||||
}
|
||||
|
14
vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/gce_zones.go
generated
vendored
14
vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/gce_zones.go
generated
vendored
@ -17,13 +17,14 @@ limitations under the License.
|
||||
package gce
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"context"
|
||||
"strings"
|
||||
|
||||
compute "google.golang.org/api/compute/v1"
|
||||
|
||||
"k8s.io/apimachinery/pkg/types"
|
||||
"k8s.io/kubernetes/pkg/cloudprovider"
|
||||
"k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud/filter"
|
||||
)
|
||||
|
||||
func newZonesMetricContext(request, region string) *metricContext {
|
||||
@ -31,7 +32,7 @@ func newZonesMetricContext(request, region string) *metricContext {
|
||||
}
|
||||
|
||||
// GetZone creates a cloudprovider.Zone of the current zone and region
|
||||
func (gce *GCECloud) GetZone() (cloudprovider.Zone, error) {
|
||||
func (gce *GCECloud) GetZone(ctx context.Context) (cloudprovider.Zone, error) {
|
||||
return cloudprovider.Zone{
|
||||
FailureDomain: gce.localZone,
|
||||
Region: gce.region,
|
||||
@ -41,7 +42,7 @@ func (gce *GCECloud) GetZone() (cloudprovider.Zone, error) {
|
||||
// GetZoneByProviderID implements Zones.GetZoneByProviderID
|
||||
// This is particularly useful in external cloud providers where the kubelet
|
||||
// does not initialize node data.
|
||||
func (gce *GCECloud) GetZoneByProviderID(providerID string) (cloudprovider.Zone, error) {
|
||||
func (gce *GCECloud) GetZoneByProviderID(ctx context.Context, providerID string) (cloudprovider.Zone, error) {
|
||||
_, zone, _, err := splitProviderID(providerID)
|
||||
if err != nil {
|
||||
return cloudprovider.Zone{}, err
|
||||
@ -56,7 +57,7 @@ func (gce *GCECloud) GetZoneByProviderID(providerID string) (cloudprovider.Zone,
|
||||
// GetZoneByNodeName implements Zones.GetZoneByNodeName
|
||||
// This is particularly useful in external cloud providers where the kubelet
|
||||
// does not initialize node data.
|
||||
func (gce *GCECloud) GetZoneByNodeName(nodeName types.NodeName) (cloudprovider.Zone, error) {
|
||||
func (gce *GCECloud) GetZoneByNodeName(ctx context.Context, nodeName types.NodeName) (cloudprovider.Zone, error) {
|
||||
instanceName := mapNodeNameToInstanceName(nodeName)
|
||||
instance, err := gce.getInstanceByName(instanceName)
|
||||
if err != nil {
|
||||
@ -72,12 +73,11 @@ func (gce *GCECloud) GetZoneByNodeName(nodeName types.NodeName) (cloudprovider.Z
|
||||
// ListZonesInRegion returns all zones in a GCP region
|
||||
func (gce *GCECloud) ListZonesInRegion(region string) ([]*compute.Zone, error) {
|
||||
mc := newZonesMetricContext("list", region)
|
||||
filter := fmt.Sprintf("region eq %v", gce.getRegionLink(region))
|
||||
list, err := gce.service.Zones.List(gce.projectID).Filter(filter).Do()
|
||||
list, err := gce.c.Zones().List(context.Background(), filter.Regexp("region", gce.getRegionLink(region)))
|
||||
if err != nil {
|
||||
return nil, mc.Observe(err)
|
||||
}
|
||||
return list.Items, mc.Observe(err)
|
||||
return list, mc.Observe(err)
|
||||
}
|
||||
|
||||
func (gce *GCECloud) getRegionLink(region string) string {
|
||||
|
66
vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/support.go
generated
vendored
Normal file
66
vendor/k8s.io/kubernetes/pkg/cloudprovider/providers/gce/support.go
generated
vendored
Normal file
@ -0,0 +1,66 @@
|
||||
/*
|
||||
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 (
|
||||
"context"
|
||||
|
||||
"k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud"
|
||||
"k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud/meta"
|
||||
)
|
||||
|
||||
// gceProjectRouter sends requests to the appropriate project ID.
|
||||
type gceProjectRouter struct {
|
||||
gce *GCECloud
|
||||
}
|
||||
|
||||
// ProjectID returns the project ID to be used for the given operation.
|
||||
func (r *gceProjectRouter) ProjectID(ctx context.Context, version meta.Version, service string) string {
|
||||
switch service {
|
||||
case "Firewalls", "Routes":
|
||||
return r.gce.NetworkProjectID()
|
||||
default:
|
||||
return r.gce.projectID
|
||||
}
|
||||
}
|
||||
|
||||
// gceRateLimiter implements cloud.RateLimiter.
|
||||
type gceRateLimiter struct {
|
||||
gce *GCECloud
|
||||
}
|
||||
|
||||
// Accept blocks until the operation can be performed.
|
||||
//
|
||||
// TODO: the current cloud provider policy doesn't seem to be correct as it
|
||||
// only rate limits the polling operations, but not the /submission/ of
|
||||
// operations.
|
||||
func (l *gceRateLimiter) Accept(ctx context.Context, key *cloud.RateLimitKey) error {
|
||||
if key.Operation == "Get" && key.Service == "Operations" {
|
||||
ch := make(chan struct{})
|
||||
go func() {
|
||||
l.gce.operationPollRateLimiter.Accept()
|
||||
close(ch)
|
||||
}()
|
||||
select {
|
||||
case <-ch:
|
||||
break
|
||||
case <-ctx.Done():
|
||||
return ctx.Err()
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
Reference in New Issue
Block a user