Compare commits

..

1 Commits

Author SHA1 Message Date
Kubernetes Publisher
2cefa64ff1 Fix Godeps.json to point to kubernetes-1.11.3 tags 2018-09-10 08:34:59 +00:00
9 changed files with 117 additions and 662 deletions

172
Godeps/Godeps.json generated
View File

@@ -188,27 +188,27 @@
},
{
"ImportPath": "golang.org/x/net/context",
"Rev": "0ed95abb35c445290478a5348a7b38bb154135fd"
"Rev": "1c05540f6879653db88113bc4a2b70aec4bd491f"
},
{
"ImportPath": "golang.org/x/net/context/ctxhttp",
"Rev": "0ed95abb35c445290478a5348a7b38bb154135fd"
"Rev": "1c05540f6879653db88113bc4a2b70aec4bd491f"
},
{
"ImportPath": "golang.org/x/net/http2",
"Rev": "0ed95abb35c445290478a5348a7b38bb154135fd"
"Rev": "1c05540f6879653db88113bc4a2b70aec4bd491f"
},
{
"ImportPath": "golang.org/x/net/http2/hpack",
"Rev": "0ed95abb35c445290478a5348a7b38bb154135fd"
"Rev": "1c05540f6879653db88113bc4a2b70aec4bd491f"
},
{
"ImportPath": "golang.org/x/net/idna",
"Rev": "0ed95abb35c445290478a5348a7b38bb154135fd"
"Rev": "1c05540f6879653db88113bc4a2b70aec4bd491f"
},
{
"ImportPath": "golang.org/x/net/lex/httplex",
"Rev": "0ed95abb35c445290478a5348a7b38bb154135fd"
"Rev": "1c05540f6879653db88113bc4a2b70aec4bd491f"
},
{
"ImportPath": "golang.org/x/oauth2",
@@ -268,323 +268,323 @@
},
{
"ImportPath": "k8s.io/api/admissionregistration/v1alpha1",
"Rev": "e86510ea3fe79b17eda7b8b3bb5cf8811d3af968"
"Rev": "4e7be11eab3ffcfc1876898b8272df53785a9504"
},
{
"ImportPath": "k8s.io/api/admissionregistration/v1beta1",
"Rev": "e86510ea3fe79b17eda7b8b3bb5cf8811d3af968"
"Rev": "4e7be11eab3ffcfc1876898b8272df53785a9504"
},
{
"ImportPath": "k8s.io/api/apps/v1",
"Rev": "e86510ea3fe79b17eda7b8b3bb5cf8811d3af968"
"Rev": "4e7be11eab3ffcfc1876898b8272df53785a9504"
},
{
"ImportPath": "k8s.io/api/apps/v1beta1",
"Rev": "e86510ea3fe79b17eda7b8b3bb5cf8811d3af968"
"Rev": "4e7be11eab3ffcfc1876898b8272df53785a9504"
},
{
"ImportPath": "k8s.io/api/apps/v1beta2",
"Rev": "e86510ea3fe79b17eda7b8b3bb5cf8811d3af968"
"Rev": "4e7be11eab3ffcfc1876898b8272df53785a9504"
},
{
"ImportPath": "k8s.io/api/authentication/v1",
"Rev": "e86510ea3fe79b17eda7b8b3bb5cf8811d3af968"
"Rev": "4e7be11eab3ffcfc1876898b8272df53785a9504"
},
{
"ImportPath": "k8s.io/api/authentication/v1beta1",
"Rev": "e86510ea3fe79b17eda7b8b3bb5cf8811d3af968"
"Rev": "4e7be11eab3ffcfc1876898b8272df53785a9504"
},
{
"ImportPath": "k8s.io/api/authorization/v1",
"Rev": "e86510ea3fe79b17eda7b8b3bb5cf8811d3af968"
"Rev": "4e7be11eab3ffcfc1876898b8272df53785a9504"
},
{
"ImportPath": "k8s.io/api/authorization/v1beta1",
"Rev": "e86510ea3fe79b17eda7b8b3bb5cf8811d3af968"
"Rev": "4e7be11eab3ffcfc1876898b8272df53785a9504"
},
{
"ImportPath": "k8s.io/api/autoscaling/v1",
"Rev": "e86510ea3fe79b17eda7b8b3bb5cf8811d3af968"
"Rev": "4e7be11eab3ffcfc1876898b8272df53785a9504"
},
{
"ImportPath": "k8s.io/api/autoscaling/v2beta1",
"Rev": "e86510ea3fe79b17eda7b8b3bb5cf8811d3af968"
"Rev": "4e7be11eab3ffcfc1876898b8272df53785a9504"
},
{
"ImportPath": "k8s.io/api/batch/v1",
"Rev": "e86510ea3fe79b17eda7b8b3bb5cf8811d3af968"
"Rev": "4e7be11eab3ffcfc1876898b8272df53785a9504"
},
{
"ImportPath": "k8s.io/api/batch/v1beta1",
"Rev": "e86510ea3fe79b17eda7b8b3bb5cf8811d3af968"
"Rev": "4e7be11eab3ffcfc1876898b8272df53785a9504"
},
{
"ImportPath": "k8s.io/api/batch/v2alpha1",
"Rev": "e86510ea3fe79b17eda7b8b3bb5cf8811d3af968"
"Rev": "4e7be11eab3ffcfc1876898b8272df53785a9504"
},
{
"ImportPath": "k8s.io/api/certificates/v1beta1",
"Rev": "e86510ea3fe79b17eda7b8b3bb5cf8811d3af968"
"Rev": "4e7be11eab3ffcfc1876898b8272df53785a9504"
},
{
"ImportPath": "k8s.io/api/core/v1",
"Rev": "e86510ea3fe79b17eda7b8b3bb5cf8811d3af968"
"Rev": "4e7be11eab3ffcfc1876898b8272df53785a9504"
},
{
"ImportPath": "k8s.io/api/events/v1beta1",
"Rev": "e86510ea3fe79b17eda7b8b3bb5cf8811d3af968"
"Rev": "4e7be11eab3ffcfc1876898b8272df53785a9504"
},
{
"ImportPath": "k8s.io/api/extensions/v1beta1",
"Rev": "e86510ea3fe79b17eda7b8b3bb5cf8811d3af968"
"Rev": "4e7be11eab3ffcfc1876898b8272df53785a9504"
},
{
"ImportPath": "k8s.io/api/imagepolicy/v1alpha1",
"Rev": "e86510ea3fe79b17eda7b8b3bb5cf8811d3af968"
"Rev": "4e7be11eab3ffcfc1876898b8272df53785a9504"
},
{
"ImportPath": "k8s.io/api/networking/v1",
"Rev": "e86510ea3fe79b17eda7b8b3bb5cf8811d3af968"
"Rev": "4e7be11eab3ffcfc1876898b8272df53785a9504"
},
{
"ImportPath": "k8s.io/api/policy/v1beta1",
"Rev": "e86510ea3fe79b17eda7b8b3bb5cf8811d3af968"
"Rev": "4e7be11eab3ffcfc1876898b8272df53785a9504"
},
{
"ImportPath": "k8s.io/api/rbac/v1",
"Rev": "e86510ea3fe79b17eda7b8b3bb5cf8811d3af968"
"Rev": "4e7be11eab3ffcfc1876898b8272df53785a9504"
},
{
"ImportPath": "k8s.io/api/rbac/v1alpha1",
"Rev": "e86510ea3fe79b17eda7b8b3bb5cf8811d3af968"
"Rev": "4e7be11eab3ffcfc1876898b8272df53785a9504"
},
{
"ImportPath": "k8s.io/api/rbac/v1beta1",
"Rev": "e86510ea3fe79b17eda7b8b3bb5cf8811d3af968"
"Rev": "4e7be11eab3ffcfc1876898b8272df53785a9504"
},
{
"ImportPath": "k8s.io/api/scheduling/v1alpha1",
"Rev": "e86510ea3fe79b17eda7b8b3bb5cf8811d3af968"
"Rev": "4e7be11eab3ffcfc1876898b8272df53785a9504"
},
{
"ImportPath": "k8s.io/api/scheduling/v1beta1",
"Rev": "e86510ea3fe79b17eda7b8b3bb5cf8811d3af968"
"Rev": "4e7be11eab3ffcfc1876898b8272df53785a9504"
},
{
"ImportPath": "k8s.io/api/settings/v1alpha1",
"Rev": "e86510ea3fe79b17eda7b8b3bb5cf8811d3af968"
"Rev": "4e7be11eab3ffcfc1876898b8272df53785a9504"
},
{
"ImportPath": "k8s.io/api/storage/v1",
"Rev": "e86510ea3fe79b17eda7b8b3bb5cf8811d3af968"
"Rev": "4e7be11eab3ffcfc1876898b8272df53785a9504"
},
{
"ImportPath": "k8s.io/api/storage/v1alpha1",
"Rev": "e86510ea3fe79b17eda7b8b3bb5cf8811d3af968"
"Rev": "4e7be11eab3ffcfc1876898b8272df53785a9504"
},
{
"ImportPath": "k8s.io/api/storage/v1beta1",
"Rev": "e86510ea3fe79b17eda7b8b3bb5cf8811d3af968"
"Rev": "4e7be11eab3ffcfc1876898b8272df53785a9504"
},
{
"ImportPath": "k8s.io/apimachinery/pkg/api/equality",
"Rev": "1525e4dadd2df06debdeb27ee24ac7db5b6413b1"
"Rev": "def12e63c512da17043b4f0293f52d1006603d9f"
},
{
"ImportPath": "k8s.io/apimachinery/pkg/api/errors",
"Rev": "1525e4dadd2df06debdeb27ee24ac7db5b6413b1"
"Rev": "def12e63c512da17043b4f0293f52d1006603d9f"
},
{
"ImportPath": "k8s.io/apimachinery/pkg/api/meta",
"Rev": "1525e4dadd2df06debdeb27ee24ac7db5b6413b1"
"Rev": "def12e63c512da17043b4f0293f52d1006603d9f"
},
{
"ImportPath": "k8s.io/apimachinery/pkg/api/resource",
"Rev": "1525e4dadd2df06debdeb27ee24ac7db5b6413b1"
"Rev": "def12e63c512da17043b4f0293f52d1006603d9f"
},
{
"ImportPath": "k8s.io/apimachinery/pkg/api/testing",
"Rev": "1525e4dadd2df06debdeb27ee24ac7db5b6413b1"
"Rev": "def12e63c512da17043b4f0293f52d1006603d9f"
},
{
"ImportPath": "k8s.io/apimachinery/pkg/api/testing/fuzzer",
"Rev": "1525e4dadd2df06debdeb27ee24ac7db5b6413b1"
"Rev": "def12e63c512da17043b4f0293f52d1006603d9f"
},
{
"ImportPath": "k8s.io/apimachinery/pkg/api/testing/roundtrip",
"Rev": "1525e4dadd2df06debdeb27ee24ac7db5b6413b1"
"Rev": "def12e63c512da17043b4f0293f52d1006603d9f"
},
{
"ImportPath": "k8s.io/apimachinery/pkg/apis/meta/fuzzer",
"Rev": "1525e4dadd2df06debdeb27ee24ac7db5b6413b1"
"Rev": "def12e63c512da17043b4f0293f52d1006603d9f"
},
{
"ImportPath": "k8s.io/apimachinery/pkg/apis/meta/internalversion",
"Rev": "1525e4dadd2df06debdeb27ee24ac7db5b6413b1"
"Rev": "def12e63c512da17043b4f0293f52d1006603d9f"
},
{
"ImportPath": "k8s.io/apimachinery/pkg/apis/meta/v1",
"Rev": "1525e4dadd2df06debdeb27ee24ac7db5b6413b1"
"Rev": "def12e63c512da17043b4f0293f52d1006603d9f"
},
{
"ImportPath": "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured",
"Rev": "1525e4dadd2df06debdeb27ee24ac7db5b6413b1"
"Rev": "def12e63c512da17043b4f0293f52d1006603d9f"
},
{
"ImportPath": "k8s.io/apimachinery/pkg/apis/meta/v1beta1",
"Rev": "1525e4dadd2df06debdeb27ee24ac7db5b6413b1"
"Rev": "def12e63c512da17043b4f0293f52d1006603d9f"
},
{
"ImportPath": "k8s.io/apimachinery/pkg/conversion",
"Rev": "1525e4dadd2df06debdeb27ee24ac7db5b6413b1"
"Rev": "def12e63c512da17043b4f0293f52d1006603d9f"
},
{
"ImportPath": "k8s.io/apimachinery/pkg/conversion/queryparams",
"Rev": "1525e4dadd2df06debdeb27ee24ac7db5b6413b1"
"Rev": "def12e63c512da17043b4f0293f52d1006603d9f"
},
{
"ImportPath": "k8s.io/apimachinery/pkg/fields",
"Rev": "1525e4dadd2df06debdeb27ee24ac7db5b6413b1"
"Rev": "def12e63c512da17043b4f0293f52d1006603d9f"
},
{
"ImportPath": "k8s.io/apimachinery/pkg/labels",
"Rev": "1525e4dadd2df06debdeb27ee24ac7db5b6413b1"
"Rev": "def12e63c512da17043b4f0293f52d1006603d9f"
},
{
"ImportPath": "k8s.io/apimachinery/pkg/runtime",
"Rev": "1525e4dadd2df06debdeb27ee24ac7db5b6413b1"
"Rev": "def12e63c512da17043b4f0293f52d1006603d9f"
},
{
"ImportPath": "k8s.io/apimachinery/pkg/runtime/schema",
"Rev": "1525e4dadd2df06debdeb27ee24ac7db5b6413b1"
"Rev": "def12e63c512da17043b4f0293f52d1006603d9f"
},
{
"ImportPath": "k8s.io/apimachinery/pkg/runtime/serializer",
"Rev": "1525e4dadd2df06debdeb27ee24ac7db5b6413b1"
"Rev": "def12e63c512da17043b4f0293f52d1006603d9f"
},
{
"ImportPath": "k8s.io/apimachinery/pkg/runtime/serializer/json",
"Rev": "1525e4dadd2df06debdeb27ee24ac7db5b6413b1"
"Rev": "def12e63c512da17043b4f0293f52d1006603d9f"
},
{
"ImportPath": "k8s.io/apimachinery/pkg/runtime/serializer/protobuf",
"Rev": "1525e4dadd2df06debdeb27ee24ac7db5b6413b1"
"Rev": "def12e63c512da17043b4f0293f52d1006603d9f"
},
{
"ImportPath": "k8s.io/apimachinery/pkg/runtime/serializer/recognizer",
"Rev": "1525e4dadd2df06debdeb27ee24ac7db5b6413b1"
"Rev": "def12e63c512da17043b4f0293f52d1006603d9f"
},
{
"ImportPath": "k8s.io/apimachinery/pkg/runtime/serializer/streaming",
"Rev": "1525e4dadd2df06debdeb27ee24ac7db5b6413b1"
"Rev": "def12e63c512da17043b4f0293f52d1006603d9f"
},
{
"ImportPath": "k8s.io/apimachinery/pkg/runtime/serializer/versioning",
"Rev": "1525e4dadd2df06debdeb27ee24ac7db5b6413b1"
"Rev": "def12e63c512da17043b4f0293f52d1006603d9f"
},
{
"ImportPath": "k8s.io/apimachinery/pkg/selection",
"Rev": "1525e4dadd2df06debdeb27ee24ac7db5b6413b1"
"Rev": "def12e63c512da17043b4f0293f52d1006603d9f"
},
{
"ImportPath": "k8s.io/apimachinery/pkg/types",
"Rev": "1525e4dadd2df06debdeb27ee24ac7db5b6413b1"
"Rev": "def12e63c512da17043b4f0293f52d1006603d9f"
},
{
"ImportPath": "k8s.io/apimachinery/pkg/util/cache",
"Rev": "1525e4dadd2df06debdeb27ee24ac7db5b6413b1"
"Rev": "def12e63c512da17043b4f0293f52d1006603d9f"
},
{
"ImportPath": "k8s.io/apimachinery/pkg/util/clock",
"Rev": "1525e4dadd2df06debdeb27ee24ac7db5b6413b1"
"Rev": "def12e63c512da17043b4f0293f52d1006603d9f"
},
{
"ImportPath": "k8s.io/apimachinery/pkg/util/diff",
"Rev": "1525e4dadd2df06debdeb27ee24ac7db5b6413b1"
"Rev": "def12e63c512da17043b4f0293f52d1006603d9f"
},
{
"ImportPath": "k8s.io/apimachinery/pkg/util/errors",
"Rev": "1525e4dadd2df06debdeb27ee24ac7db5b6413b1"
"Rev": "def12e63c512da17043b4f0293f52d1006603d9f"
},
{
"ImportPath": "k8s.io/apimachinery/pkg/util/framer",
"Rev": "1525e4dadd2df06debdeb27ee24ac7db5b6413b1"
"Rev": "def12e63c512da17043b4f0293f52d1006603d9f"
},
{
"ImportPath": "k8s.io/apimachinery/pkg/util/httpstream",
"Rev": "1525e4dadd2df06debdeb27ee24ac7db5b6413b1"
"Rev": "def12e63c512da17043b4f0293f52d1006603d9f"
},
{
"ImportPath": "k8s.io/apimachinery/pkg/util/httpstream/spdy",
"Rev": "1525e4dadd2df06debdeb27ee24ac7db5b6413b1"
"Rev": "def12e63c512da17043b4f0293f52d1006603d9f"
},
{
"ImportPath": "k8s.io/apimachinery/pkg/util/intstr",
"Rev": "1525e4dadd2df06debdeb27ee24ac7db5b6413b1"
"Rev": "def12e63c512da17043b4f0293f52d1006603d9f"
},
{
"ImportPath": "k8s.io/apimachinery/pkg/util/json",
"Rev": "1525e4dadd2df06debdeb27ee24ac7db5b6413b1"
"Rev": "def12e63c512da17043b4f0293f52d1006603d9f"
},
{
"ImportPath": "k8s.io/apimachinery/pkg/util/mergepatch",
"Rev": "1525e4dadd2df06debdeb27ee24ac7db5b6413b1"
"Rev": "def12e63c512da17043b4f0293f52d1006603d9f"
},
{
"ImportPath": "k8s.io/apimachinery/pkg/util/net",
"Rev": "1525e4dadd2df06debdeb27ee24ac7db5b6413b1"
"Rev": "def12e63c512da17043b4f0293f52d1006603d9f"
},
{
"ImportPath": "k8s.io/apimachinery/pkg/util/remotecommand",
"Rev": "1525e4dadd2df06debdeb27ee24ac7db5b6413b1"
"Rev": "def12e63c512da17043b4f0293f52d1006603d9f"
},
{
"ImportPath": "k8s.io/apimachinery/pkg/util/runtime",
"Rev": "1525e4dadd2df06debdeb27ee24ac7db5b6413b1"
"Rev": "def12e63c512da17043b4f0293f52d1006603d9f"
},
{
"ImportPath": "k8s.io/apimachinery/pkg/util/sets",
"Rev": "1525e4dadd2df06debdeb27ee24ac7db5b6413b1"
"Rev": "def12e63c512da17043b4f0293f52d1006603d9f"
},
{
"ImportPath": "k8s.io/apimachinery/pkg/util/strategicpatch",
"Rev": "1525e4dadd2df06debdeb27ee24ac7db5b6413b1"
"Rev": "def12e63c512da17043b4f0293f52d1006603d9f"
},
{
"ImportPath": "k8s.io/apimachinery/pkg/util/validation",
"Rev": "1525e4dadd2df06debdeb27ee24ac7db5b6413b1"
"Rev": "def12e63c512da17043b4f0293f52d1006603d9f"
},
{
"ImportPath": "k8s.io/apimachinery/pkg/util/validation/field",
"Rev": "1525e4dadd2df06debdeb27ee24ac7db5b6413b1"
"Rev": "def12e63c512da17043b4f0293f52d1006603d9f"
},
{
"ImportPath": "k8s.io/apimachinery/pkg/util/wait",
"Rev": "1525e4dadd2df06debdeb27ee24ac7db5b6413b1"
"Rev": "def12e63c512da17043b4f0293f52d1006603d9f"
},
{
"ImportPath": "k8s.io/apimachinery/pkg/util/yaml",
"Rev": "1525e4dadd2df06debdeb27ee24ac7db5b6413b1"
"Rev": "def12e63c512da17043b4f0293f52d1006603d9f"
},
{
"ImportPath": "k8s.io/apimachinery/pkg/version",
"Rev": "1525e4dadd2df06debdeb27ee24ac7db5b6413b1"
"Rev": "def12e63c512da17043b4f0293f52d1006603d9f"
},
{
"ImportPath": "k8s.io/apimachinery/pkg/watch",
"Rev": "1525e4dadd2df06debdeb27ee24ac7db5b6413b1"
"Rev": "def12e63c512da17043b4f0293f52d1006603d9f"
},
{
"ImportPath": "k8s.io/apimachinery/third_party/forked/golang/json",
"Rev": "1525e4dadd2df06debdeb27ee24ac7db5b6413b1"
"Rev": "def12e63c512da17043b4f0293f52d1006603d9f"
},
{
"ImportPath": "k8s.io/apimachinery/third_party/forked/golang/netutil",
"Rev": "1525e4dadd2df06debdeb27ee24ac7db5b6413b1"
"Rev": "def12e63c512da17043b4f0293f52d1006603d9f"
},
{
"ImportPath": "k8s.io/apimachinery/third_party/forked/golang/reflect",
"Rev": "1525e4dadd2df06debdeb27ee24ac7db5b6413b1"
"Rev": "def12e63c512da17043b4f0293f52d1006603d9f"
},
{
"ImportPath": "k8s.io/kube-openapi/pkg/util/proto",

View File

@@ -33,10 +33,6 @@ import (
)
func NewSimpleDynamicClient(scheme *runtime.Scheme, objects ...runtime.Object) *FakeDynamicClient {
// In order to use List with this client, you have to have the v1.List registered in your scheme. Neat thing though
// it does NOT have to be the *same* list
scheme.AddKnownTypeWithName(schema.GroupVersionKind{Group: "fake-dynamic-client-group", Version: "v1", Kind: "List"}, &unstructured.UnstructuredList{})
codecs := serializer.NewCodecFactory(scheme)
o := testing.NewObjectTracker(scheme, codecs.UniversalDecoder())
for _, obj := range objects {
@@ -276,11 +272,11 @@ func (c *dynamicResourceClient) List(opts metav1.ListOptions) (*unstructured.Uns
switch {
case len(c.namespace) == 0:
obj, err = c.client.Fake.
Invokes(testing.NewRootListAction(c.resource, schema.GroupVersionKind{Group: "fake-dynamic-client-group", Version: "v1", Kind: "" /*List is appended by the tracker automatically*/}, opts), &metav1.Status{Status: "dynamic list fail"})
Invokes(testing.NewRootListAction(c.resource, schema.GroupVersionKind{Version: "v1", Kind: "List"}, opts), &metav1.Status{Status: "dynamic list fail"})
case len(c.namespace) > 0:
obj, err = c.client.Fake.
Invokes(testing.NewListAction(c.resource, schema.GroupVersionKind{Group: "fake-dynamic-client-group", Version: "v1", Kind: "" /*List is appended by the tracker automatically*/}, c.namespace, opts), &metav1.Status{Status: "dynamic list fail"})
Invokes(testing.NewListAction(c.resource, schema.GroupVersionKind{Version: "v1", Kind: "List"}, c.namespace, opts), &metav1.Status{Status: "dynamic list fail"})
}
@@ -303,15 +299,13 @@ func (c *dynamicResourceClient) List(opts metav1.ListOptions) (*unstructured.Uns
}
list := &unstructured.UnstructuredList{}
list.SetResourceVersion(entireList.GetResourceVersion())
for i := range entireList.Items {
item := &entireList.Items[i]
for _, item := range entireList.Items {
metadata, err := meta.Accessor(item)
if err != nil {
return nil, err
}
if label.Matches(labels.Set(metadata.GetLabels())) {
list.Items = append(list.Items, *item)
list.Items = append(list.Items, item)
}
}
return list, nil

View File

@@ -1,66 +0,0 @@
/*
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 fake
import (
"testing"
"k8s.io/apimachinery/pkg/api/equality"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/apimachinery/pkg/util/diff"
)
func newUnstructured(apiVersion, kind, namespace, name string) *unstructured.Unstructured {
return &unstructured.Unstructured{
Object: map[string]interface{}{
"apiVersion": apiVersion,
"kind": kind,
"metadata": map[string]interface{}{
"namespace": namespace,
"name": name,
},
},
}
}
func TestList(t *testing.T) {
scheme := runtime.NewScheme()
client := NewSimpleDynamicClient(scheme,
newUnstructured("group/version", "TheKind", "ns-foo", "name-foo"),
newUnstructured("group2/version", "TheKind", "ns-foo", "name2-foo"),
newUnstructured("group/version", "TheKind", "ns-foo", "name-bar"),
newUnstructured("group/version", "TheKind", "ns-foo", "name-baz"),
newUnstructured("group2/version", "TheKind", "ns-foo", "name2-baz"),
)
listFirst, err := client.Resource(schema.GroupVersionResource{Group: "group", Version: "version", Resource: "thekinds"}).List(metav1.ListOptions{})
if err != nil {
t.Fatal(err)
}
expected := []unstructured.Unstructured{
*newUnstructured("group/version", "TheKind", "ns-foo", "name-foo"),
*newUnstructured("group/version", "TheKind", "ns-foo", "name-bar"),
*newUnstructured("group/version", "TheKind", "ns-foo", "name-baz"),
}
if !equality.Semantic.DeepEqual(listFirst.Items, expected) {
t.Fatal(diff.ObjectGoPrintDiff(expected, listFirst.Items))
}
}

View File

@@ -455,9 +455,17 @@ func (r *Request) URL() *url.URL {
// finalURLTemplate is similar to URL(), but will make all specific parameter values equal
// - instead of name or namespace, "{name}" and "{namespace}" will be used, and all query
// parameters will be reset. This creates a copy of the url so as not to change the
// underlying object.
// parameters will be reset. This creates a copy of the request so as not to change the
// underlying object. This means some useful request info (like the types of field
// selectors in use) will be lost.
// TODO: preserve field selector keys
func (r Request) finalURLTemplate() url.URL {
if len(r.resourceName) != 0 {
r.resourceName = "{name}"
}
if r.namespaceSet && len(r.namespace) != 0 {
r.namespace = "{namespace}"
}
newParams := url.Values{}
v := []string{"{value}"}
for k := range r.params {
@@ -465,59 +473,6 @@ func (r Request) finalURLTemplate() url.URL {
}
r.params = newParams
url := r.URL()
segments := strings.Split(r.URL().Path, "/")
groupIndex := 0
index := 0
if r.URL() != nil && r.baseURL != nil && strings.Contains(r.URL().Path, r.baseURL.Path) {
groupIndex += len(strings.Split(r.baseURL.Path, "/"))
}
if groupIndex >= len(segments) {
return *url
}
const CoreGroupPrefix = "api"
const NamedGroupPrefix = "apis"
isCoreGroup := segments[groupIndex] == CoreGroupPrefix
isNamedGroup := segments[groupIndex] == NamedGroupPrefix
if isCoreGroup {
// checking the case of core group with /api/v1/... format
index = groupIndex + 2
} else if isNamedGroup {
// checking the case of named group with /apis/apps/v1/... format
index = groupIndex + 3
} else {
// this should not happen that the only two possibilities are /api... and /apis..., just want to put an
// outlet here in case more API groups are added in future if ever possible:
// https://kubernetes.io/docs/concepts/overview/kubernetes-api/#api-groups
// if a wrong API groups name is encountered, return the {prefix} for url.Path
url.Path = "/{prefix}"
url.RawQuery = ""
return *url
}
//switch segLength := len(segments) - index; segLength {
switch {
// case len(segments) - index == 1:
// resource (with no name) do nothing
case len(segments)-index == 2:
// /$RESOURCE/$NAME: replace $NAME with {name}
segments[index+1] = "{name}"
case len(segments)-index == 3:
if segments[index+2] == "finalize" || segments[index+2] == "status" {
// /$RESOURCE/$NAME/$SUBRESOURCE: replace $NAME with {name}
segments[index+1] = "{name}"
} else {
// /namespace/$NAMESPACE/$RESOURCE: replace $NAMESPACE with {namespace}
segments[index+1] = "{namespace}"
}
case len(segments)-index >= 4:
segments[index+1] = "{namespace}"
// /namespace/$NAMESPACE/$RESOURCE/$NAME: replace $NAMESPACE with {namespace}, $NAME with {name}
if segments[index+3] != "finalize" && segments[index+3] != "status" {
// /$RESOURCE/$NAME/$SUBRESOURCE: replace $NAME with {name}
segments[index+3] = "{name}"
}
}
url.Path = path.Join(segments...)
return *url
}

View File

@@ -340,169 +340,21 @@ func TestResultIntoWithNoBodyReturnsErr(t *testing.T) {
}
func TestURLTemplate(t *testing.T) {
uri, _ := url.Parse("http://localhost/some/base/url/path")
testCases := []struct {
Request *Request
ExpectedFullURL string
ExpectedFinalURL string
}{
{
// non dynamic client
Request: NewRequest(nil, "POST", uri, "", ContentConfig{GroupVersion: &schema.GroupVersion{Group: "test"}}, Serializers{}, nil, nil, 0).
Prefix("api", "v1").Resource("r1").Namespace("ns").Name("nm").Param("p0", "v0"),
ExpectedFullURL: "http://localhost/some/base/url/path/api/v1/namespaces/ns/r1/nm?p0=v0",
ExpectedFinalURL: "http://localhost/some/base/url/path/api/v1/namespaces/%7Bnamespace%7D/r1/%7Bname%7D?p0=%7Bvalue%7D",
},
{
// non dynamic client with wrong api group
Request: NewRequest(nil, "POST", uri, "", ContentConfig{GroupVersion: &schema.GroupVersion{Group: "test"}}, Serializers{}, nil, nil, 0).
Prefix("pre1", "v1").Resource("r1").Namespace("ns").Name("nm").Param("p0", "v0"),
ExpectedFullURL: "http://localhost/some/base/url/path/pre1/v1/namespaces/ns/r1/nm?p0=v0",
ExpectedFinalURL: "http://localhost/%7Bprefix%7D",
},
{
// dynamic client with core group + namespace + resourceResource (with name)
// /api/$RESOURCEVERSION/namespaces/$NAMESPACE/$RESOURCE/%NAME
Request: NewRequest(nil, "DELETE", uri, "", ContentConfig{GroupVersion: &schema.GroupVersion{Group: "test"}}, Serializers{}, nil, nil, 0).
Prefix("/api/v1/namespaces/ns/r1/name1"),
ExpectedFullURL: "http://localhost/some/base/url/path/api/v1/namespaces/ns/r1/name1",
ExpectedFinalURL: "http://localhost/some/base/url/path/api/v1/namespaces/%7Bnamespace%7D/r1/%7Bname%7D",
},
{
// dynamic client with named group + namespace + resourceResource (with name)
// /apis/$NAMEDGROUPNAME/$RESOURCEVERSION/namespaces/$NAMESPACE/$RESOURCE/%NAME
Request: NewRequest(nil, "DELETE", uri, "", ContentConfig{GroupVersion: &schema.GroupVersion{Group: "test"}}, Serializers{}, nil, nil, 0).
Prefix("/apis/g1/v1/namespaces/ns/r1/name1"),
ExpectedFullURL: "http://localhost/some/base/url/path/apis/g1/v1/namespaces/ns/r1/name1",
ExpectedFinalURL: "http://localhost/some/base/url/path/apis/g1/v1/namespaces/%7Bnamespace%7D/r1/%7Bname%7D",
},
{
// dynamic client with core group + namespace + resourceResource (with NO name)
// /api/$RESOURCEVERSION/namespaces/$NAMESPACE/$RESOURCE
Request: NewRequest(nil, "DELETE", uri, "", ContentConfig{GroupVersion: &schema.GroupVersion{Group: "test"}}, Serializers{}, nil, nil, 0).
Prefix("/api/v1/namespaces/ns/r1"),
ExpectedFullURL: "http://localhost/some/base/url/path/api/v1/namespaces/ns/r1",
ExpectedFinalURL: "http://localhost/some/base/url/path/api/v1/namespaces/%7Bnamespace%7D/r1",
},
{
// dynamic client with named group + namespace + resourceResource (with NO name)
// /apis/$NAMEDGROUPNAME/$RESOURCEVERSION/namespaces/$NAMESPACE/$RESOURCE
Request: NewRequest(nil, "DELETE", uri, "", ContentConfig{GroupVersion: &schema.GroupVersion{Group: "test"}}, Serializers{}, nil, nil, 0).
Prefix("/apis/g1/v1/namespaces/ns/r1"),
ExpectedFullURL: "http://localhost/some/base/url/path/apis/g1/v1/namespaces/ns/r1",
ExpectedFinalURL: "http://localhost/some/base/url/path/apis/g1/v1/namespaces/%7Bnamespace%7D/r1",
},
{
// dynamic client with core group + resourceResource (with name)
// /api/$RESOURCEVERSION/$RESOURCE/%NAME
Request: NewRequest(nil, "DELETE", uri, "", ContentConfig{GroupVersion: &schema.GroupVersion{Group: "test"}}, Serializers{}, nil, nil, 0).
Prefix("/api/v1/r1/name1"),
ExpectedFullURL: "http://localhost/some/base/url/path/api/v1/r1/name1",
ExpectedFinalURL: "http://localhost/some/base/url/path/api/v1/r1/%7Bname%7D",
},
{
// dynamic client with named group + resourceResource (with name)
// /apis/$NAMEDGROUPNAME/$RESOURCEVERSION/$RESOURCE/%NAME
Request: NewRequest(nil, "DELETE", uri, "", ContentConfig{GroupVersion: &schema.GroupVersion{Group: "test"}}, Serializers{}, nil, nil, 0).
Prefix("/apis/g1/v1/r1/name1"),
ExpectedFullURL: "http://localhost/some/base/url/path/apis/g1/v1/r1/name1",
ExpectedFinalURL: "http://localhost/some/base/url/path/apis/g1/v1/r1/%7Bname%7D",
},
{
// dynamic client with named group + namespace + resourceResource (with name) + subresource
// /apis/$NAMEDGROUPNAME/$RESOURCEVERSION/namespaces/$NAMESPACE/$RESOURCE/%NAME/$SUBRESOURCE
Request: NewRequest(nil, "DELETE", uri, "", ContentConfig{GroupVersion: &schema.GroupVersion{Group: "test"}}, Serializers{}, nil, nil, 0).
Prefix("/apis/namespaces/namespaces/namespaces/namespaces/namespaces/namespaces/finalize"),
ExpectedFullURL: "http://localhost/some/base/url/path/apis/namespaces/namespaces/namespaces/namespaces/namespaces/namespaces/finalize",
ExpectedFinalURL: "http://localhost/some/base/url/path/apis/namespaces/namespaces/namespaces/%7Bnamespace%7D/namespaces/%7Bname%7D/finalize",
},
{
// dynamic client with named group + namespace + resourceResource (with name)
// /apis/$NAMEDGROUPNAME/$RESOURCEVERSION/namespaces/$NAMESPACE/$RESOURCE/%NAME
Request: NewRequest(nil, "DELETE", uri, "", ContentConfig{GroupVersion: &schema.GroupVersion{Group: "test"}}, Serializers{}, nil, nil, 0).
Prefix("/apis/namespaces/namespaces/namespaces/namespaces/namespaces/namespaces"),
ExpectedFullURL: "http://localhost/some/base/url/path/apis/namespaces/namespaces/namespaces/namespaces/namespaces/namespaces",
ExpectedFinalURL: "http://localhost/some/base/url/path/apis/namespaces/namespaces/namespaces/%7Bnamespace%7D/namespaces/%7Bname%7D",
},
{
// dynamic client with named group + namespace + resourceResource (with NO name) + subresource
// /apis/$NAMEDGROUPNAME/$RESOURCEVERSION/namespaces/$NAMESPACE/$RESOURCE/%SUBRESOURCE
Request: NewRequest(nil, "DELETE", uri, "", ContentConfig{GroupVersion: &schema.GroupVersion{Group: "test"}}, Serializers{}, nil, nil, 0).
Prefix("/apis/namespaces/namespaces/namespaces/namespaces/namespaces/finalize"),
ExpectedFullURL: "http://localhost/some/base/url/path/apis/namespaces/namespaces/namespaces/namespaces/namespaces/finalize",
ExpectedFinalURL: "http://localhost/some/base/url/path/apis/namespaces/namespaces/namespaces/%7Bnamespace%7D/namespaces/finalize",
},
{
// dynamic client with named group + namespace + resourceResource (with NO name) + subresource
// /apis/$NAMEDGROUPNAME/$RESOURCEVERSION/namespaces/$NAMESPACE/$RESOURCE/%SUBRESOURCE
Request: NewRequest(nil, "DELETE", uri, "", ContentConfig{GroupVersion: &schema.GroupVersion{Group: "test"}}, Serializers{}, nil, nil, 0).
Prefix("/apis/namespaces/namespaces/namespaces/namespaces/namespaces/status"),
ExpectedFullURL: "http://localhost/some/base/url/path/apis/namespaces/namespaces/namespaces/namespaces/namespaces/status",
ExpectedFinalURL: "http://localhost/some/base/url/path/apis/namespaces/namespaces/namespaces/%7Bnamespace%7D/namespaces/status",
},
{
// dynamic client with named group + namespace + resourceResource (with no name)
// /apis/$NAMEDGROUPNAME/$RESOURCEVERSION/namespaces/$NAMESPACE/$RESOURCE/%NAME
Request: NewRequest(nil, "DELETE", uri, "", ContentConfig{GroupVersion: &schema.GroupVersion{Group: "test"}}, Serializers{}, nil, nil, 0).
Prefix("/apis/namespaces/namespaces/namespaces/namespaces/namespaces"),
ExpectedFullURL: "http://localhost/some/base/url/path/apis/namespaces/namespaces/namespaces/namespaces/namespaces",
ExpectedFinalURL: "http://localhost/some/base/url/path/apis/namespaces/namespaces/namespaces/%7Bnamespace%7D/namespaces",
},
{
// dynamic client with named group + resourceResource (with name) + subresource
// /apis/$NAMEDGROUPNAME/$RESOURCEVERSION/namespaces/$NAMESPACE/$RESOURCE/%NAME
Request: NewRequest(nil, "DELETE", uri, "", ContentConfig{GroupVersion: &schema.GroupVersion{Group: "test"}}, Serializers{}, nil, nil, 0).
Prefix("/apis/namespaces/namespaces/namespaces/namespaces/finalize"),
ExpectedFullURL: "http://localhost/some/base/url/path/apis/namespaces/namespaces/namespaces/namespaces/finalize",
ExpectedFinalURL: "http://localhost/some/base/url/path/apis/namespaces/namespaces/namespaces/%7Bname%7D/finalize",
},
{
// dynamic client with named group + resourceResource (with name) + subresource
// /apis/$NAMEDGROUPNAME/$RESOURCEVERSION/namespaces/$NAMESPACE/$RESOURCE/%NAME
Request: NewRequest(nil, "DELETE", uri, "", ContentConfig{GroupVersion: &schema.GroupVersion{Group: "test"}}, Serializers{}, nil, nil, 0).
Prefix("/apis/namespaces/namespaces/namespaces/namespaces/status"),
ExpectedFullURL: "http://localhost/some/base/url/path/apis/namespaces/namespaces/namespaces/namespaces/status",
ExpectedFinalURL: "http://localhost/some/base/url/path/apis/namespaces/namespaces/namespaces/%7Bname%7D/status",
},
{
// dynamic client with named group + resourceResource (with name)
// /apis/$NAMEDGROUPNAME/$RESOURCEVERSION/$RESOURCE/%NAME
Request: NewRequest(nil, "DELETE", uri, "", ContentConfig{GroupVersion: &schema.GroupVersion{Group: "test"}}, Serializers{}, nil, nil, 0).
Prefix("/apis/namespaces/namespaces/namespaces/namespaces"),
ExpectedFullURL: "http://localhost/some/base/url/path/apis/namespaces/namespaces/namespaces/namespaces",
ExpectedFinalURL: "http://localhost/some/base/url/path/apis/namespaces/namespaces/namespaces/%7Bname%7D",
},
{
// dynamic client with named group + resourceResource (with no name)
// /apis/$NAMEDGROUPNAME/$RESOURCEVERSION/$RESOURCE/%NAME
Request: NewRequest(nil, "DELETE", uri, "", ContentConfig{GroupVersion: &schema.GroupVersion{Group: "test"}}, Serializers{}, nil, nil, 0).
Prefix("/apis/namespaces/namespaces/namespaces"),
ExpectedFullURL: "http://localhost/some/base/url/path/apis/namespaces/namespaces/namespaces",
ExpectedFinalURL: "http://localhost/some/base/url/path/apis/namespaces/namespaces/namespaces",
},
{
// dynamic client with wrong api group + namespace + resourceResource (with name) + subresource
// /apis/$NAMEDGROUPNAME/$RESOURCEVERSION/namespaces/$NAMESPACE/$RESOURCE/%NAME/$SUBRESOURCE
Request: NewRequest(nil, "DELETE", uri, "", ContentConfig{GroupVersion: &schema.GroupVersion{Group: "test"}}, Serializers{}, nil, nil, 0).
Prefix("/pre1/namespaces/namespaces/namespaces/namespaces/namespaces/namespaces/finalize"),
ExpectedFullURL: "http://localhost/some/base/url/path/pre1/namespaces/namespaces/namespaces/namespaces/namespaces/namespaces/finalize",
ExpectedFinalURL: "http://localhost/%7Bprefix%7D",
},
uri, _ := url.Parse("http://localhost")
r := NewRequest(nil, "POST", uri, "", ContentConfig{GroupVersion: &schema.GroupVersion{Group: "test"}}, Serializers{}, nil, nil, 0)
r.Prefix("pre1").Resource("r1").Namespace("ns").Name("nm").Param("p0", "v0")
full := r.URL()
if full.String() != "http://localhost/pre1/namespaces/ns/r1/nm?p0=v0" {
t.Errorf("unexpected initial URL: %s", full)
}
for i, testCase := range testCases {
r := testCase.Request
full := r.URL()
if full.String() != testCase.ExpectedFullURL {
t.Errorf("%d: unexpected initial URL: %s %s", i, full, testCase.ExpectedFullURL)
}
actualURL := r.finalURLTemplate()
actual := actualURL.String()
if actual != testCase.ExpectedFinalURL {
t.Errorf("%d: unexpected URL template: %s %s", i, actual, testCase.ExpectedFinalURL)
}
if r.URL().String() != full.String() {
t.Errorf("%d, creating URL template changed request: %s -> %s", i, full.String(), r.URL().String())
}
actualURL := r.finalURLTemplate()
actual := actualURL.String()
expected := "http://localhost/pre1/namespaces/%7Bnamespace%7D/r1/%7Bname%7D?p0=%7Bvalue%7D"
if actual != expected {
t.Errorf("unexpected URL template: %s %s", actual, expected)
}
if r.URL().String() != full.String() {
t.Errorf("creating URL template changed request: %s -> %s", full.String(), r.URL().String())
}
}

View File

@@ -1,69 +0,0 @@
/*
Copyright 2015 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 leaderelection
import (
"net/http"
"sync"
"time"
)
// HealthzAdaptor associates the /healthz endpoint with the LeaderElection object.
// It helps deal with the /healthz endpoint being set up prior to the LeaderElection.
// This contains the code needed to act as an adaptor between the leader
// election code the health check code. It allows us to provide health
// status about the leader election. Most specifically about if the leader
// has failed to renew without exiting the process. In that case we should
// report not healthy and rely on the kubelet to take down the process.
type HealthzAdaptor struct {
pointerLock sync.Mutex
le *LeaderElector
timeout time.Duration
}
// Name returns the name of the health check we are implementing.
func (l *HealthzAdaptor) Name() string {
return "leaderElection"
}
// Check is called by the healthz endpoint handler.
// It fails (returns an error) if we own the lease but had not been able to renew it.
func (l *HealthzAdaptor) Check(req *http.Request) error {
l.pointerLock.Lock()
defer l.pointerLock.Unlock()
if l.le == nil {
return nil
}
return l.le.Check(l.timeout)
}
// SetLeaderElection ties a leader election object to a HealthzAdaptor
func (l *HealthzAdaptor) SetLeaderElection(le *LeaderElector) {
l.pointerLock.Lock()
defer l.pointerLock.Unlock()
l.le = le
}
// NewLeaderHealthzAdaptor creates a basic healthz adaptor to monitor a leader election.
// timeout determines the time beyond the lease expiry to be allowed for timeout.
// checks within the timeout period after the lease expires will still return healthy.
func NewLeaderHealthzAdaptor(timeout time.Duration) *HealthzAdaptor {
result := &HealthzAdaptor{
timeout: timeout,
}
return result
}

View File

@@ -1,175 +0,0 @@
/*
Copyright 2015 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 leaderelection
import (
"fmt"
"testing"
"time"
"k8s.io/apimachinery/pkg/util/clock"
rl "k8s.io/client-go/tools/leaderelection/resourcelock"
"net/http"
)
type fakeLock struct {
identity string
}
// Get is a dummy to allow us to have a fakeLock for testing.
func (fl *fakeLock) Get() (ler *rl.LeaderElectionRecord, err error) {
return nil, nil
}
// Create is a dummy to allow us to have a fakeLock for testing.
func (fl *fakeLock) Create(ler rl.LeaderElectionRecord) error {
return nil
}
// Update is a dummy to allow us to have a fakeLock for testing.
func (fl *fakeLock) Update(ler rl.LeaderElectionRecord) error {
return nil
}
// RecordEvent is a dummy to allow us to have a fakeLock for testing.
func (fl *fakeLock) RecordEvent(string) {}
// Identity is a dummy to allow us to have a fakeLock for testing.
func (fl *fakeLock) Identity() string {
return fl.identity
}
// Describe is a dummy to allow us to have a fakeLock for testing.
func (fl *fakeLock) Describe() string {
return "Dummy implementation of lock for testing"
}
// TestLeaderElectionHealthChecker tests that the healthcheck for leader election handles its edge cases.
func TestLeaderElectionHealthChecker(t *testing.T) {
current := time.Now()
req := &http.Request{}
tests := []struct {
description string
expected error
adaptorTimeout time.Duration
elector *LeaderElector
}{
{
description: "call check before leader elector initialized",
expected: nil,
adaptorTimeout: time.Second * 20,
elector: nil,
},
{
description: "call check when the the lease is far expired",
expected: fmt.Errorf("failed election to renew leadership on lease %s", "foo"),
adaptorTimeout: time.Second * 20,
elector: &LeaderElector{
config: LeaderElectionConfig{
Lock: &fakeLock{identity: "healthTest"},
LeaseDuration: time.Minute,
Name: "foo",
},
observedRecord: rl.LeaderElectionRecord{
HolderIdentity: "healthTest",
},
observedTime: current,
clock: clock.NewFakeClock(current.Add(time.Hour)),
},
},
{
description: "call check when the the lease is far expired but held by another server",
expected: nil,
adaptorTimeout: time.Second * 20,
elector: &LeaderElector{
config: LeaderElectionConfig{
Lock: &fakeLock{identity: "healthTest"},
LeaseDuration: time.Minute,
Name: "foo",
},
observedRecord: rl.LeaderElectionRecord{
HolderIdentity: "otherServer",
},
observedTime: current,
clock: clock.NewFakeClock(current.Add(time.Hour)),
},
},
{
description: "call check when the the lease is not expired",
expected: nil,
adaptorTimeout: time.Second * 20,
elector: &LeaderElector{
config: LeaderElectionConfig{
Lock: &fakeLock{identity: "healthTest"},
LeaseDuration: time.Minute,
Name: "foo",
},
observedRecord: rl.LeaderElectionRecord{
HolderIdentity: "healthTest",
},
observedTime: current,
clock: clock.NewFakeClock(current),
},
},
{
description: "call check when the the lease is expired but inside the timeout",
expected: nil,
adaptorTimeout: time.Second * 20,
elector: &LeaderElector{
config: LeaderElectionConfig{
Lock: &fakeLock{identity: "healthTest"},
LeaseDuration: time.Minute,
Name: "foo",
},
observedRecord: rl.LeaderElectionRecord{
HolderIdentity: "healthTest",
},
observedTime: current,
clock: clock.NewFakeClock(current.Add(time.Minute).Add(time.Second)),
},
},
}
for _, test := range tests {
adaptor := NewLeaderHealthzAdaptor(test.adaptorTimeout)
if adaptor.le != nil {
t.Errorf("[%s] leaderChecker started with a LeaderElector %v", test.description, adaptor.le)
}
if test.elector != nil {
test.elector.config.WatchDog = adaptor
adaptor.SetLeaderElection(test.elector)
if adaptor.le == nil {
t.Errorf("[%s] adaptor failed to set the LeaderElector", test.description)
}
}
err := adaptor.Check(req)
if test.expected == nil {
if err == nil {
continue
}
t.Errorf("[%s] called check, expected no error but received \"%v\"", test.description, err)
} else {
if err == nil {
t.Errorf("[%s] called check and failed to received the expected error \"%v\"", test.description, test.expected)
}
if err.Error() != test.expected.Error() {
t.Errorf("[%s] called check, expected %v, received %v", test.description, test.expected, err)
}
}
}
}

View File

@@ -55,7 +55,6 @@ import (
"k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/util/clock"
"k8s.io/apimachinery/pkg/util/runtime"
"k8s.io/apimachinery/pkg/util/wait"
rl "k8s.io/client-go/tools/leaderelection/resourcelock"
@@ -90,7 +89,6 @@ func NewLeaderElector(lec LeaderElectionConfig) (*LeaderElector, error) {
}
return &LeaderElector{
config: lec,
clock: clock.RealClock{},
}, nil
}
@@ -112,13 +110,6 @@ type LeaderElectionConfig struct {
// Callbacks are callbacks that are triggered during certain lifecycle
// events of the LeaderElector
Callbacks LeaderCallbacks
// WatchDog is the associated health checker
// WatchDog may be null if its not needed/configured.
WatchDog *HealthzAdaptor
// Name is the name of the resource lock for debugging
Name string
}
// LeaderCallbacks are callbacks that are triggered during certain
@@ -151,12 +142,6 @@ type LeaderElector struct {
// value observedRecord.HolderIdentity if the transition has
// not yet been reported.
reportedLeader string
// clock is wrapper around time to allow for less flaky testing
clock clock.Clock
// name is the name of the resource lock for debugging
name string
}
// Run starts the leader election loop
@@ -179,9 +164,6 @@ func RunOrDie(lec LeaderElectionConfig) {
if err != nil {
panic(err)
}
if lec.WatchDog != nil {
lec.WatchDog.SetLeaderElection(le)
}
le.Run()
}
@@ -257,14 +239,14 @@ func (le *LeaderElector) tryAcquireOrRenew() bool {
return false
}
le.observedRecord = leaderElectionRecord
le.observedTime = le.clock.Now()
le.observedTime = time.Now()
return true
}
// 2. Record obtained, check the Identity & Time
if !reflect.DeepEqual(le.observedRecord, *oldLeaderElectionRecord) {
le.observedRecord = *oldLeaderElectionRecord
le.observedTime = le.clock.Now()
le.observedTime = time.Now()
}
if le.observedTime.Add(le.config.LeaseDuration).After(now.Time) &&
oldLeaderElectionRecord.HolderIdentity != le.config.Lock.Identity() {
@@ -287,7 +269,7 @@ func (le *LeaderElector) tryAcquireOrRenew() bool {
return false
}
le.observedRecord = leaderElectionRecord
le.observedTime = le.clock.Now()
le.observedTime = time.Now()
return true
}
@@ -300,19 +282,3 @@ func (l *LeaderElector) maybeReportTransition() {
go l.config.Callbacks.OnNewLeader(l.reportedLeader)
}
}
// Check will determine if the current lease is expired by more than timeout.
func (le *LeaderElector) Check(maxTolerableExpiredLease time.Duration) error {
if !le.IsLeader() {
// Currently not concerned with the case that we are hot standby
return nil
}
// If we are more than timeout seconds after the lease duration that is past the timeout
// on the lease renew. Time to start reporting ourselves as unhealthy. We should have
// died but conditions like deadlock can prevent this. (See #70819)
if le.clock.Since(le.observedTime) > le.config.LeaseDuration+maxTolerableExpiredLease {
return fmt.Errorf("failed election to renew leadership on lease %s", le.config.Name)
}
return nil
}

View File

@@ -26,7 +26,6 @@ import (
"k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/util/clock"
fakecorev1 "k8s.io/client-go/kubernetes/typed/core/v1/fake"
core "k8s.io/client-go/testing"
rl "k8s.io/client-go/tools/leaderelection/resourcelock"
@@ -258,7 +257,6 @@ func testTryAcquireOrRenew(t *testing.T, objectType string) {
config: lec,
observedRecord: test.observedRecord,
observedTime: test.observedTime,
clock: clock.RealClock{},
}
if test.expectSuccess != le.tryAcquireOrRenew() {