From 9b9eff51f2fea74b09301881655d3844fcaddf68 Mon Sep 17 00:00:00 2001 From: Manuel de Brito Fontes Date: Tue, 10 May 2016 00:14:47 -0300 Subject: [PATCH 1/4] Allow authentication in Ingress rules --- ingress/controllers/nginx/auth/main.go | 141 ++++++++++++++++++ ingress/controllers/nginx/auth/main_test.go | 141 ++++++++++++++++++ .../nginx/examples/auth/auth-ingress.yaml | 18 +++ 3 files changed, 300 insertions(+) create mode 100644 ingress/controllers/nginx/auth/main.go create mode 100644 ingress/controllers/nginx/auth/main_test.go create mode 100644 ingress/controllers/nginx/examples/auth/auth-ingress.yaml diff --git a/ingress/controllers/nginx/auth/main.go b/ingress/controllers/nginx/auth/main.go new file mode 100644 index 0000000000..4d74267d81 --- /dev/null +++ b/ingress/controllers/nginx/auth/main.go @@ -0,0 +1,141 @@ +/* +Copyright 2015 The Kubernetes Authors All rights reserved. + +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 auth + +import ( + "bytes" + "errors" + "fmt" + "io/ioutil" + + "k8s.io/kubernetes/pkg/api" + "k8s.io/kubernetes/pkg/apis/extensions" + client "k8s.io/kubernetes/pkg/client/unversioned" +) + +const ( + authType = "ingress-nginx.kubernetes.io/auth-type" + authSecret = "ingress-nginx.kubernetes.io/auth-secret" + authRealm = "ingress-nginx.kubernetes.io/auth-realm" + + defAuthRealm = "Authentication Required" +) + +var ( + authTypeRegex = "basic|digest" + authDir = "/etc/nginx/auth" + + // ErrInvalidAuthType is return in case of unsupported authentication type + ErrInvalidAuthType = errors.New("invalid authentication type") + + // ErrMissingAuthType is return when the annotation for authentication is missing + ErrMissingAuthType = errors.New("authentication type is missing") + + // ErrMissingSecretName is returned when the name of the secret is missing + ErrMissingSecretName = errors.New("secret name is missing") +) + +// Nginx returns authentication configuration for an Ingress rule +type Nginx struct { + Type string + Secret *api.Secret + Realm string + File string +} + +type ingAnnotations map[string]string + +func (a ingAnnotations) authType() (string, error) { + val, ok := a[authType] + if !ok { + return "", ErrMissingAuthType + } + + if val != "basic" || val != "digest" { + return "", ErrInvalidAuthType + } + + return val, nil +} + +func (a ingAnnotations) realm() string { + val, ok := a[authRealm] + if !ok { + return defAuthRealm + } + + return val +} + +func (a ingAnnotations) secretName() (string, error) { + val, ok := a[authSecret] + if !ok { + return "", ErrMissingSecretName + } + + return val, nil +} + +// Parse parses the annotations contained in the ingress rule +// used to add authentication in the paths defined in the rule +// and generated an htpasswd compatible file to be used as source +// during the authentication process +func Parse(kubeClient client.Interface, ing *extensions.Ingress) (*Nginx, error) { + at, err := ingAnnotations(ing.GetAnnotations()).authType() + if err != nil { + return nil, err + } + + s, err := ingAnnotations(ing.GetAnnotations()).secretName() + if err != nil { + return nil, err + } + + secret, err := kubeClient.Secrets(ing.Namespace).Get(s) + if err != nil { + return nil, err + } + + realm := ingAnnotations(ing.GetAnnotations()).realm() + + passFile := fmt.Sprintf("%v/%v-%v.passwd", authDir, ing.GetNamespace(), ing.GetName()) + err = dumpSecret(passFile, at, secret) + if err != nil { + return nil, err + } + + n := &Nginx{ + Type: at, + Secret: secret, + Realm: realm, + File: passFile, + } + + return n, nil +} + +// dumpSecret dumps the content of a secret into a file +// in the expected format for the specified authorization +func dumpSecret(filename, auth string, secret *api.Secret) error { + buf := bytes.NewBuffer([]byte{}) + + for key, value := range secret.Data { + fmt.Fprintf(buf, "%v:%s\n", key, value) + } + + return ioutil.WriteFile(filename, buf.Bytes(), 600) +} diff --git a/ingress/controllers/nginx/auth/main_test.go b/ingress/controllers/nginx/auth/main_test.go new file mode 100644 index 0000000000..2a11dd4946 --- /dev/null +++ b/ingress/controllers/nginx/auth/main_test.go @@ -0,0 +1,141 @@ +/* +Copyright 2015 The Kubernetes Authors All rights reserved. + +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 auth + +import ( + "testing" + + "k8s.io/kubernetes/pkg/api" + "k8s.io/kubernetes/pkg/apis/extensions" + "k8s.io/kubernetes/pkg/client/unversioned" + "k8s.io/kubernetes/pkg/client/unversioned/testclient" + "k8s.io/kubernetes/pkg/util/intstr" +) + +func buildIngress() *extensions.Ingress { + defaultBackend := extensions.IngressBackend{ + ServiceName: "default-backend", + ServicePort: intstr.FromInt(80), + } + + return &extensions.Ingress{ + ObjectMeta: api.ObjectMeta{ + Name: "foo", + Namespace: api.NamespaceDefault, + }, + Spec: extensions.IngressSpec{ + Backend: &extensions.IngressBackend{ + ServiceName: "default-backend", + ServicePort: intstr.FromInt(80), + }, + Rules: []extensions.IngressRule{ + { + Host: "foo.bar.com", + IngressRuleValue: extensions.IngressRuleValue{ + HTTP: &extensions.HTTPIngressRuleValue{ + Paths: []extensions.HTTPIngressPath{ + { + Path: "/foo", + Backend: defaultBackend, + }, + }, + }, + }, + }, + }, + }, + } +} + +type secretsClient struct { + unversioned.Interface +} + +func mockClient() *testclient.Fake { + secretObj := &api.Secret{ + ObjectMeta: api.ObjectMeta{ + Namespace: api.NamespaceDefault, + Name: "demo-secret", + }, + } + + return testclient.NewSimpleFake(secretObj) +} + +func TestAnnotations(t *testing.T) { + ing := buildIngress() + + _, err := ingAnnotations(ing.GetAnnotations()).authType() + if err == nil { + t.Error("Expected a validation error") + } + realm := ingAnnotations(ing.GetAnnotations()).realm() + if realm != defAuthRealm { + t.Error("Expected default realm") + } + + _, err = ingAnnotations(ing.GetAnnotations()).secretName() + if err == nil { + t.Error("Expected a validation error") + } + + data := map[string]string{} + data[authType] = "demo" + data[authSecret] = "demo-secret" + data[authRealm] = "demo" + ing.SetAnnotations(data) + + _, err = ingAnnotations(ing.GetAnnotations()).authType() + if err == nil { + t.Error("Expected a validation error") + } + + realm = ingAnnotations(ing.GetAnnotations()).realm() + if realm != "demo" { + t.Errorf("Expected demo as realm but returned %s", realm) + } + + secret, err := ingAnnotations(ing.GetAnnotations()).secretName() + if err != nil { + t.Error("Unexpec error %v", err) + } + if secret != "demo-secret" { + t.Errorf("Expected demo-secret as realm but returned %s", secret) + } +} + +func TestIngressWithoutAuth(t *testing.T) { + ing := buildIngress() + client := mockClient() + _, err := Parse(client, ing) + if err == nil { + t.Error("Expected error with ingress without annotations") + } + + if err != ErrMissingAuthType { + t.Errorf("Expected MissingAuthType error but returned %v", err) + } +} + +func TestIngressBasicAuth(t *testing.T) { +} + +func TestIngressDigestAuth(t *testing.T) { +} + +func TestIngressMissingAnnotation(t *testing.T) { +} diff --git a/ingress/controllers/nginx/examples/auth/auth-ingress.yaml b/ingress/controllers/nginx/examples/auth/auth-ingress.yaml new file mode 100644 index 0000000000..0942cbb699 --- /dev/null +++ b/ingress/controllers/nginx/examples/auth/auth-ingress.yaml @@ -0,0 +1,18 @@ +# An Ingress with 2 hosts and 3 endpoints +apiVersion: extensions/v1beta1 +kind: Ingress +metadata: + name: echo-with-auth +annotations: + ingress-nginx.kubernetes.io/auth-type: basic + ingress-nginx.kubernetes.io/auth-secret: echo-auth-secret + ingress-nginx.kubernetes.io/auth-realm: "Ingress with Basic Authentication" +spec: + rules: + - host: foo.bar.com + http: + paths: + - path: / + backend: + serviceName: echoheaders-x + servicePort: 80 From ff786c4aa806316b4cd2995cf07e6ae5caccae53 Mon Sep 17 00:00:00 2001 From: Manuel de Brito Fontes Date: Tue, 10 May 2016 18:43:55 -0300 Subject: [PATCH 2/4] Add unversioned/testclient package --- ingress/Godeps/Godeps.json | 5 + .../client/unversioned/testclient/actions.go | 446 ++++++++++++++++++ .../testclient/fake_componentstatuses.go | 44 ++ .../unversioned/testclient/fake_configmaps.go | 78 +++ .../testclient/fake_daemon_sets.go | 83 ++++ .../testclient/fake_deployments.go | 105 +++++ .../unversioned/testclient/fake_endpoints.go | 74 +++ .../unversioned/testclient/fake_events.go | 151 ++++++ .../fake_horizontal_pod_autoscalers.go | 164 +++++++ .../unversioned/testclient/fake_ingress.go | 84 ++++ .../unversioned/testclient/fake_jobs.go | 147 ++++++ .../testclient/fake_limit_ranges.go | 74 +++ .../unversioned/testclient/fake_namespaces.go | 103 ++++ .../unversioned/testclient/fake_nodes.go | 88 ++++ .../fake_persistent_volume_claims.go | 81 ++++ .../testclient/fake_persistent_volumes.go | 86 ++++ .../testclient/fake_pod_templates.go | 74 +++ .../unversioned/testclient/fake_pods.go | 117 +++++ .../testclient/fake_podsecuritypolicy.go | 73 +++ .../testclient/fake_replica_sets.go | 83 ++++ .../fake_replication_controllers.go | 82 ++++ .../testclient/fake_resource_quotas.go | 83 ++++ .../unversioned/testclient/fake_scales.go | 52 ++ .../unversioned/testclient/fake_secrets.go | 74 +++ .../testclient/fake_service_accounts.go | 74 +++ .../unversioned/testclient/fake_services.go | 88 ++++ .../testclient/fake_thirdpartyresources.go | 82 ++++ .../client/unversioned/testclient/fixture.go | 313 ++++++++++++ .../unversioned/testclient/testclient.go | 419 ++++++++++++++++ 29 files changed, 3427 insertions(+) create mode 100644 ingress/vendor/k8s.io/kubernetes/pkg/client/unversioned/testclient/actions.go create mode 100644 ingress/vendor/k8s.io/kubernetes/pkg/client/unversioned/testclient/fake_componentstatuses.go create mode 100644 ingress/vendor/k8s.io/kubernetes/pkg/client/unversioned/testclient/fake_configmaps.go create mode 100644 ingress/vendor/k8s.io/kubernetes/pkg/client/unversioned/testclient/fake_daemon_sets.go create mode 100644 ingress/vendor/k8s.io/kubernetes/pkg/client/unversioned/testclient/fake_deployments.go create mode 100644 ingress/vendor/k8s.io/kubernetes/pkg/client/unversioned/testclient/fake_endpoints.go create mode 100644 ingress/vendor/k8s.io/kubernetes/pkg/client/unversioned/testclient/fake_events.go create mode 100644 ingress/vendor/k8s.io/kubernetes/pkg/client/unversioned/testclient/fake_horizontal_pod_autoscalers.go create mode 100644 ingress/vendor/k8s.io/kubernetes/pkg/client/unversioned/testclient/fake_ingress.go create mode 100644 ingress/vendor/k8s.io/kubernetes/pkg/client/unversioned/testclient/fake_jobs.go create mode 100644 ingress/vendor/k8s.io/kubernetes/pkg/client/unversioned/testclient/fake_limit_ranges.go create mode 100644 ingress/vendor/k8s.io/kubernetes/pkg/client/unversioned/testclient/fake_namespaces.go create mode 100644 ingress/vendor/k8s.io/kubernetes/pkg/client/unversioned/testclient/fake_nodes.go create mode 100644 ingress/vendor/k8s.io/kubernetes/pkg/client/unversioned/testclient/fake_persistent_volume_claims.go create mode 100644 ingress/vendor/k8s.io/kubernetes/pkg/client/unversioned/testclient/fake_persistent_volumes.go create mode 100644 ingress/vendor/k8s.io/kubernetes/pkg/client/unversioned/testclient/fake_pod_templates.go create mode 100644 ingress/vendor/k8s.io/kubernetes/pkg/client/unversioned/testclient/fake_pods.go create mode 100644 ingress/vendor/k8s.io/kubernetes/pkg/client/unversioned/testclient/fake_podsecuritypolicy.go create mode 100644 ingress/vendor/k8s.io/kubernetes/pkg/client/unversioned/testclient/fake_replica_sets.go create mode 100644 ingress/vendor/k8s.io/kubernetes/pkg/client/unversioned/testclient/fake_replication_controllers.go create mode 100644 ingress/vendor/k8s.io/kubernetes/pkg/client/unversioned/testclient/fake_resource_quotas.go create mode 100644 ingress/vendor/k8s.io/kubernetes/pkg/client/unversioned/testclient/fake_scales.go create mode 100644 ingress/vendor/k8s.io/kubernetes/pkg/client/unversioned/testclient/fake_secrets.go create mode 100644 ingress/vendor/k8s.io/kubernetes/pkg/client/unversioned/testclient/fake_service_accounts.go create mode 100644 ingress/vendor/k8s.io/kubernetes/pkg/client/unversioned/testclient/fake_services.go create mode 100644 ingress/vendor/k8s.io/kubernetes/pkg/client/unversioned/testclient/fake_thirdpartyresources.go create mode 100644 ingress/vendor/k8s.io/kubernetes/pkg/client/unversioned/testclient/fixture.go create mode 100644 ingress/vendor/k8s.io/kubernetes/pkg/client/unversioned/testclient/testclient.go diff --git a/ingress/Godeps/Godeps.json b/ingress/Godeps/Godeps.json index f89d5c711e..bd4b3c3204 100644 --- a/ingress/Godeps/Godeps.json +++ b/ingress/Godeps/Godeps.json @@ -622,6 +622,11 @@ "Comment": "v1.3.0-alpha.3-574-gdee2433", "Rev": "dee24333ffe6942519476bb1db4c7d6eadf65cdb" }, + { + "ImportPath": "k8s.io/kubernetes/pkg/client/unversioned/testclient", + "Comment": "v1.3.0-alpha.3-574-gdee2433", + "Rev": "dee24333ffe6942519476bb1db4c7d6eadf65cdb" + }, { "ImportPath": "k8s.io/kubernetes/pkg/cloudprovider", "Comment": "v1.3.0-alpha.3-574-gdee2433", diff --git a/ingress/vendor/k8s.io/kubernetes/pkg/client/unversioned/testclient/actions.go b/ingress/vendor/k8s.io/kubernetes/pkg/client/unversioned/testclient/actions.go new file mode 100644 index 0000000000..1e5a5e4701 --- /dev/null +++ b/ingress/vendor/k8s.io/kubernetes/pkg/client/unversioned/testclient/actions.go @@ -0,0 +1,446 @@ +/* +Copyright 2015 The Kubernetes Authors All rights reserved. + +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 testclient + +import ( + "strings" + + "k8s.io/kubernetes/pkg/api" + "k8s.io/kubernetes/pkg/fields" + "k8s.io/kubernetes/pkg/labels" + "k8s.io/kubernetes/pkg/runtime" +) + +func NewRootGetAction(resource, name string) GetActionImpl { + action := GetActionImpl{} + action.Verb = "get" + action.Resource = resource + action.Name = name + + return action +} + +func NewGetAction(resource, namespace, name string) GetActionImpl { + action := GetActionImpl{} + action.Verb = "get" + action.Resource = resource + action.Namespace = namespace + action.Name = name + + return action +} + +func NewRootListAction(resource string, opts api.ListOptions) ListActionImpl { + action := ListActionImpl{} + action.Verb = "list" + action.Resource = resource + labelSelector := opts.LabelSelector + if labelSelector == nil { + labelSelector = labels.Everything() + } + fieldSelector := opts.FieldSelector + if fieldSelector == nil { + fieldSelector = fields.Everything() + } + action.ListRestrictions = ListRestrictions{labelSelector, fieldSelector} + + return action +} + +func NewListAction(resource, namespace string, opts api.ListOptions) ListActionImpl { + action := ListActionImpl{} + action.Verb = "list" + action.Resource = resource + action.Namespace = namespace + labelSelector := opts.LabelSelector + if labelSelector == nil { + labelSelector = labels.Everything() + } + fieldSelector := opts.FieldSelector + if fieldSelector == nil { + fieldSelector = fields.Everything() + } + action.ListRestrictions = ListRestrictions{labelSelector, fieldSelector} + + return action +} + +func NewRootCreateAction(resource string, object runtime.Object) CreateActionImpl { + action := CreateActionImpl{} + action.Verb = "create" + action.Resource = resource + action.Object = object + + return action +} + +func NewCreateAction(resource, namespace string, object runtime.Object) CreateActionImpl { + action := CreateActionImpl{} + action.Verb = "create" + action.Resource = resource + action.Namespace = namespace + action.Object = object + + return action +} + +func NewRootUpdateAction(resource string, object runtime.Object) UpdateActionImpl { + action := UpdateActionImpl{} + action.Verb = "update" + action.Resource = resource + action.Object = object + + return action +} + +func NewUpdateAction(resource, namespace string, object runtime.Object) UpdateActionImpl { + action := UpdateActionImpl{} + action.Verb = "update" + action.Resource = resource + action.Namespace = namespace + action.Object = object + + return action +} + +func NewRootPatchAction(resource string, object runtime.Object) PatchActionImpl { + action := PatchActionImpl{} + action.Verb = "patch" + action.Resource = resource + action.Object = object + + return action +} + +func NewPatchAction(resource, namespace string, object runtime.Object) PatchActionImpl { + action := PatchActionImpl{} + action.Verb = "patch" + action.Resource = resource + action.Namespace = namespace + action.Object = object + + return action +} + +func NewUpdateSubresourceAction(resource, subresource, namespace string, object runtime.Object) UpdateActionImpl { + action := UpdateActionImpl{} + action.Verb = "update" + action.Resource = resource + action.Subresource = subresource + action.Namespace = namespace + action.Object = object + + return action +} + +func NewRootDeleteAction(resource, name string) DeleteActionImpl { + action := DeleteActionImpl{} + action.Verb = "delete" + action.Resource = resource + action.Name = name + + return action +} + +func NewDeleteAction(resource, namespace, name string) DeleteActionImpl { + action := DeleteActionImpl{} + action.Verb = "delete" + action.Resource = resource + action.Namespace = namespace + action.Name = name + + return action +} + +func NewRootDeleteCollectionAction(resource string, opts api.ListOptions) DeleteCollectionActionImpl { + action := DeleteCollectionActionImpl{} + action.Verb = "delete-collection" + action.Resource = resource + labelSelector := opts.LabelSelector + if labelSelector == nil { + labelSelector = labels.Everything() + } + fieldSelector := opts.FieldSelector + if fieldSelector == nil { + fieldSelector = fields.Everything() + } + action.ListRestrictions = ListRestrictions{labelSelector, fieldSelector} + + return action +} + +func NewDeleteCollectionAction(resource, namespace string, opts api.ListOptions) DeleteCollectionActionImpl { + action := DeleteCollectionActionImpl{} + action.Verb = "delete-collection" + action.Resource = resource + action.Namespace = namespace + labelSelector := opts.LabelSelector + if labelSelector == nil { + labelSelector = labels.Everything() + } + fieldSelector := opts.FieldSelector + if fieldSelector == nil { + fieldSelector = fields.Everything() + } + action.ListRestrictions = ListRestrictions{labelSelector, fieldSelector} + + return action +} + +func NewRootWatchAction(resource string, opts api.ListOptions) WatchActionImpl { + action := WatchActionImpl{} + action.Verb = "watch" + action.Resource = resource + labelSelector := opts.LabelSelector + if labelSelector == nil { + labelSelector = labels.Everything() + } + fieldSelector := opts.FieldSelector + if fieldSelector == nil { + fieldSelector = fields.Everything() + } + action.WatchRestrictions = WatchRestrictions{labelSelector, fieldSelector, opts.ResourceVersion} + + return action +} + +func NewWatchAction(resource, namespace string, opts api.ListOptions) WatchActionImpl { + action := WatchActionImpl{} + action.Verb = "watch" + action.Resource = resource + action.Namespace = namespace + labelSelector := opts.LabelSelector + if labelSelector == nil { + labelSelector = labels.Everything() + } + fieldSelector := opts.FieldSelector + if fieldSelector == nil { + fieldSelector = fields.Everything() + } + action.WatchRestrictions = WatchRestrictions{labelSelector, fieldSelector, opts.ResourceVersion} + + return action +} + +func NewProxyGetAction(resource, namespace, scheme, name, port, path string, params map[string]string) ProxyGetActionImpl { + action := ProxyGetActionImpl{} + action.Verb = "get" + action.Resource = resource + action.Namespace = namespace + action.Scheme = scheme + action.Name = name + action.Port = port + action.Path = path + action.Params = params + return action +} + +type ListRestrictions struct { + Labels labels.Selector + Fields fields.Selector +} +type WatchRestrictions struct { + Labels labels.Selector + Fields fields.Selector + ResourceVersion string +} + +type Action interface { + GetNamespace() string + GetVerb() string + GetResource() string + GetSubresource() string + Matches(verb, resource string) bool +} + +type GenericAction interface { + Action + GetValue() interface{} +} + +type GetAction interface { + Action + GetName() string +} + +type ListAction interface { + Action + GetListRestrictions() ListRestrictions +} + +type CreateAction interface { + Action + GetObject() runtime.Object +} + +type UpdateAction interface { + Action + GetObject() runtime.Object +} + +type DeleteAction interface { + Action + GetName() string +} + +type WatchAction interface { + Action + GetWatchRestrictions() WatchRestrictions +} + +type ProxyGetAction interface { + Action + GetScheme() string + GetName() string + GetPort() string + GetPath() string + GetParams() map[string]string +} + +type ActionImpl struct { + Namespace string + Verb string + Resource string + Subresource string +} + +func (a ActionImpl) GetNamespace() string { + return a.Namespace +} +func (a ActionImpl) GetVerb() string { + return a.Verb +} +func (a ActionImpl) GetResource() string { + return a.Resource +} +func (a ActionImpl) GetSubresource() string { + return a.Subresource +} +func (a ActionImpl) Matches(verb, resource string) bool { + return strings.ToLower(verb) == strings.ToLower(a.Verb) && + strings.ToLower(resource) == strings.ToLower(a.Resource) +} + +type GenericActionImpl struct { + ActionImpl + Value interface{} +} + +func (a GenericActionImpl) GetValue() interface{} { + return a.Value +} + +type GetActionImpl struct { + ActionImpl + Name string +} + +func (a GetActionImpl) GetName() string { + return a.Name +} + +type ListActionImpl struct { + ActionImpl + ListRestrictions ListRestrictions +} + +func (a ListActionImpl) GetListRestrictions() ListRestrictions { + return a.ListRestrictions +} + +type CreateActionImpl struct { + ActionImpl + Object runtime.Object +} + +func (a CreateActionImpl) GetObject() runtime.Object { + return a.Object +} + +type UpdateActionImpl struct { + ActionImpl + Object runtime.Object +} + +func (a UpdateActionImpl) GetObject() runtime.Object { + return a.Object +} + +type PatchActionImpl struct { + ActionImpl + Object runtime.Object +} + +func (a PatchActionImpl) GetObject() runtime.Object { + return a.Object +} + +type DeleteActionImpl struct { + ActionImpl + Name string +} + +func (a DeleteActionImpl) GetName() string { + return a.Name +} + +type DeleteCollectionActionImpl struct { + ActionImpl + ListRestrictions ListRestrictions +} + +func (a DeleteCollectionActionImpl) GetListRestrictions() ListRestrictions { + return a.ListRestrictions +} + +type WatchActionImpl struct { + ActionImpl + WatchRestrictions WatchRestrictions +} + +func (a WatchActionImpl) GetWatchRestrictions() WatchRestrictions { + return a.WatchRestrictions +} + +type ProxyGetActionImpl struct { + ActionImpl + Scheme string + Name string + Port string + Path string + Params map[string]string +} + +func (a ProxyGetActionImpl) GetScheme() string { + return a.Scheme +} + +func (a ProxyGetActionImpl) GetName() string { + return a.Name +} + +func (a ProxyGetActionImpl) GetPort() string { + return a.Port +} + +func (a ProxyGetActionImpl) GetPath() string { + return a.Path +} + +func (a ProxyGetActionImpl) GetParams() map[string]string { + return a.Params +} diff --git a/ingress/vendor/k8s.io/kubernetes/pkg/client/unversioned/testclient/fake_componentstatuses.go b/ingress/vendor/k8s.io/kubernetes/pkg/client/unversioned/testclient/fake_componentstatuses.go new file mode 100644 index 0000000000..34bf210d47 --- /dev/null +++ b/ingress/vendor/k8s.io/kubernetes/pkg/client/unversioned/testclient/fake_componentstatuses.go @@ -0,0 +1,44 @@ +/* +Copyright 2015 The Kubernetes Authors All rights reserved. + +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 testclient + +import ( + "k8s.io/kubernetes/pkg/api" +) + +// Fake implements ComponentStatusInterface. +type FakeComponentStatuses struct { + Fake *Fake +} + +func (c *FakeComponentStatuses) Get(name string) (*api.ComponentStatus, error) { + obj, err := c.Fake.Invokes(NewRootGetAction("componentstatuses", name), &api.ComponentStatus{}) + if obj == nil { + return nil, err + } + + return obj.(*api.ComponentStatus), err +} + +func (c *FakeComponentStatuses) List(opts api.ListOptions) (result *api.ComponentStatusList, err error) { + obj, err := c.Fake.Invokes(NewRootListAction("componentstatuses", opts), &api.ComponentStatusList{}) + if obj == nil { + return nil, err + } + + return obj.(*api.ComponentStatusList), err +} diff --git a/ingress/vendor/k8s.io/kubernetes/pkg/client/unversioned/testclient/fake_configmaps.go b/ingress/vendor/k8s.io/kubernetes/pkg/client/unversioned/testclient/fake_configmaps.go new file mode 100644 index 0000000000..17a5bfeb81 --- /dev/null +++ b/ingress/vendor/k8s.io/kubernetes/pkg/client/unversioned/testclient/fake_configmaps.go @@ -0,0 +1,78 @@ +/* +Copyright 2015 The Kubernetes Authors All rights reserved. + +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 testclient + +import ( + "k8s.io/kubernetes/pkg/api" + "k8s.io/kubernetes/pkg/watch" +) + +const ( + configMapResourceName string = "configMaps" +) + +// FakeConfigMaps implements ConfigMapInterface. Meant to be embedded into a struct to get a default +// implementation. This makes faking out just the method you want to test easier. +type FakeConfigMaps struct { + Fake *Fake + Namespace string +} + +func (c *FakeConfigMaps) Get(name string) (*api.ConfigMap, error) { + obj, err := c.Fake.Invokes(NewGetAction(configMapResourceName, c.Namespace, name), &api.ConfigMap{}) + if obj == nil { + return nil, err + } + + return obj.(*api.ConfigMap), err +} + +func (c *FakeConfigMaps) List(opts api.ListOptions) (*api.ConfigMapList, error) { + obj, err := c.Fake.Invokes(NewListAction(configMapResourceName, c.Namespace, opts), &api.ConfigMapList{}) + if obj == nil { + return nil, err + } + + return obj.(*api.ConfigMapList), err +} + +func (c *FakeConfigMaps) Create(cfg *api.ConfigMap) (*api.ConfigMap, error) { + obj, err := c.Fake.Invokes(NewCreateAction(configMapResourceName, c.Namespace, cfg), cfg) + if obj == nil { + return nil, err + } + + return obj.(*api.ConfigMap), err +} + +func (c *FakeConfigMaps) Update(cfg *api.ConfigMap) (*api.ConfigMap, error) { + obj, err := c.Fake.Invokes(NewUpdateAction(configMapResourceName, c.Namespace, cfg), cfg) + if obj == nil { + return nil, err + } + + return obj.(*api.ConfigMap), err +} + +func (c *FakeConfigMaps) Delete(name string) error { + _, err := c.Fake.Invokes(NewDeleteAction(configMapResourceName, c.Namespace, name), &api.ConfigMap{}) + return err +} + +func (c *FakeConfigMaps) Watch(opts api.ListOptions) (watch.Interface, error) { + return c.Fake.InvokesWatch(NewWatchAction(configMapResourceName, c.Namespace, opts)) +} diff --git a/ingress/vendor/k8s.io/kubernetes/pkg/client/unversioned/testclient/fake_daemon_sets.go b/ingress/vendor/k8s.io/kubernetes/pkg/client/unversioned/testclient/fake_daemon_sets.go new file mode 100644 index 0000000000..d0e1e73e14 --- /dev/null +++ b/ingress/vendor/k8s.io/kubernetes/pkg/client/unversioned/testclient/fake_daemon_sets.go @@ -0,0 +1,83 @@ +/* +Copyright 2015 The Kubernetes Authors All rights reserved. + +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 testclient + +import ( + "k8s.io/kubernetes/pkg/api" + "k8s.io/kubernetes/pkg/apis/extensions" + kclientlib "k8s.io/kubernetes/pkg/client/unversioned" + "k8s.io/kubernetes/pkg/watch" +) + +// FakeDaemonSet implements DaemonInterface. Meant to be embedded into a struct to get a default +// implementation. This makes faking out just the method you want to test easier. +type FakeDaemonSets struct { + Fake *FakeExperimental + Namespace string +} + +// Ensure statically that FakeDaemonSets implements DaemonInterface. +var _ kclientlib.DaemonSetInterface = &FakeDaemonSets{} + +func (c *FakeDaemonSets) Get(name string) (*extensions.DaemonSet, error) { + obj, err := c.Fake.Invokes(NewGetAction("daemonsets", c.Namespace, name), &extensions.DaemonSet{}) + if obj == nil { + return nil, err + } + return obj.(*extensions.DaemonSet), err +} + +func (c *FakeDaemonSets) List(opts api.ListOptions) (*extensions.DaemonSetList, error) { + obj, err := c.Fake.Invokes(NewListAction("daemonsets", c.Namespace, opts), &extensions.DaemonSetList{}) + if obj == nil { + return nil, err + } + return obj.(*extensions.DaemonSetList), err +} + +func (c *FakeDaemonSets) Create(daemon *extensions.DaemonSet) (*extensions.DaemonSet, error) { + obj, err := c.Fake.Invokes(NewCreateAction("daemonsets", c.Namespace, daemon), &extensions.DaemonSet{}) + if obj == nil { + return nil, err + } + return obj.(*extensions.DaemonSet), err +} + +func (c *FakeDaemonSets) Update(daemon *extensions.DaemonSet) (*extensions.DaemonSet, error) { + obj, err := c.Fake.Invokes(NewUpdateAction("daemonsets", c.Namespace, daemon), &extensions.DaemonSet{}) + if obj == nil { + return nil, err + } + return obj.(*extensions.DaemonSet), err +} + +func (c *FakeDaemonSets) UpdateStatus(daemon *extensions.DaemonSet) (*extensions.DaemonSet, error) { + obj, err := c.Fake.Invokes(NewUpdateSubresourceAction("daemonsets", "status", c.Namespace, daemon), &extensions.DaemonSet{}) + if obj == nil { + return nil, err + } + return obj.(*extensions.DaemonSet), err +} + +func (c *FakeDaemonSets) Delete(name string) error { + _, err := c.Fake.Invokes(NewDeleteAction("daemonsets", c.Namespace, name), &extensions.DaemonSet{}) + return err +} + +func (c *FakeDaemonSets) Watch(opts api.ListOptions) (watch.Interface, error) { + return c.Fake.InvokesWatch(NewWatchAction("daemonsets", c.Namespace, opts)) +} diff --git a/ingress/vendor/k8s.io/kubernetes/pkg/client/unversioned/testclient/fake_deployments.go b/ingress/vendor/k8s.io/kubernetes/pkg/client/unversioned/testclient/fake_deployments.go new file mode 100644 index 0000000000..f53f271989 --- /dev/null +++ b/ingress/vendor/k8s.io/kubernetes/pkg/client/unversioned/testclient/fake_deployments.go @@ -0,0 +1,105 @@ +/* +Copyright 2015 The Kubernetes Authors All rights reserved. + +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 testclient + +import ( + "k8s.io/kubernetes/pkg/api" + "k8s.io/kubernetes/pkg/apis/extensions" + "k8s.io/kubernetes/pkg/labels" + "k8s.io/kubernetes/pkg/watch" +) + +// FakeDeployments implements DeploymentsInterface. Meant to be embedded into a struct to get a default +// implementation. This makes faking out just the methods you want to test easier. +type FakeDeployments struct { + Fake *FakeExperimental + Namespace string +} + +func (c *FakeDeployments) Get(name string) (*extensions.Deployment, error) { + obj, err := c.Fake.Invokes(NewGetAction("deployments", c.Namespace, name), &extensions.Deployment{}) + if obj == nil { + return nil, err + } + + return obj.(*extensions.Deployment), err +} + +func (c *FakeDeployments) List(opts api.ListOptions) (*extensions.DeploymentList, error) { + obj, err := c.Fake.Invokes(NewListAction("deployments", c.Namespace, opts), &extensions.DeploymentList{}) + if obj == nil { + return nil, err + } + label := opts.LabelSelector + if label == nil { + label = labels.Everything() + } + list := &extensions.DeploymentList{} + for _, deployment := range obj.(*extensions.DeploymentList).Items { + if label.Matches(labels.Set(deployment.Labels)) { + list.Items = append(list.Items, deployment) + } + } + return list, err +} + +func (c *FakeDeployments) Create(deployment *extensions.Deployment) (*extensions.Deployment, error) { + obj, err := c.Fake.Invokes(NewCreateAction("deployments", c.Namespace, deployment), deployment) + if obj == nil { + return nil, err + } + + return obj.(*extensions.Deployment), err +} + +func (c *FakeDeployments) Update(deployment *extensions.Deployment) (*extensions.Deployment, error) { + obj, err := c.Fake.Invokes(NewUpdateAction("deployments", c.Namespace, deployment), deployment) + if obj == nil { + return nil, err + } + + return obj.(*extensions.Deployment), err +} + +func (c *FakeDeployments) UpdateStatus(deployment *extensions.Deployment) (*extensions.Deployment, error) { + obj, err := c.Fake.Invokes(NewUpdateSubresourceAction("deployments", "status", c.Namespace, deployment), deployment) + if obj == nil { + return nil, err + } + + return obj.(*extensions.Deployment), err +} + +func (c *FakeDeployments) Delete(name string, options *api.DeleteOptions) error { + _, err := c.Fake.Invokes(NewDeleteAction("deployments", c.Namespace, name), &extensions.Deployment{}) + return err +} + +func (c *FakeDeployments) Watch(opts api.ListOptions) (watch.Interface, error) { + return c.Fake.InvokesWatch(NewWatchAction("deployments", c.Namespace, opts)) +} + +func (c *FakeDeployments) Rollback(deploymentRollback *extensions.DeploymentRollback) error { + action := CreateActionImpl{} + action.Verb = "create" + action.Resource = "deployments" + action.Subresource = "rollback" + action.Object = deploymentRollback + + _, err := c.Fake.Invokes(action, deploymentRollback) + return err +} diff --git a/ingress/vendor/k8s.io/kubernetes/pkg/client/unversioned/testclient/fake_endpoints.go b/ingress/vendor/k8s.io/kubernetes/pkg/client/unversioned/testclient/fake_endpoints.go new file mode 100644 index 0000000000..68f6178f77 --- /dev/null +++ b/ingress/vendor/k8s.io/kubernetes/pkg/client/unversioned/testclient/fake_endpoints.go @@ -0,0 +1,74 @@ +/* +Copyright 2014 The Kubernetes Authors All rights reserved. + +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 testclient + +import ( + "k8s.io/kubernetes/pkg/api" + "k8s.io/kubernetes/pkg/watch" +) + +// FakeEndpoints implements EndpointInterface. Meant to be embedded into a struct to get a default +// implementation. This makes faking out just the method you want to test easier. +type FakeEndpoints struct { + Fake *Fake + Namespace string +} + +func (c *FakeEndpoints) Get(name string) (*api.Endpoints, error) { + obj, err := c.Fake.Invokes(NewGetAction("endpoints", c.Namespace, name), &api.Endpoints{}) + if obj == nil { + return nil, err + } + + return obj.(*api.Endpoints), err +} + +func (c *FakeEndpoints) List(opts api.ListOptions) (*api.EndpointsList, error) { + obj, err := c.Fake.Invokes(NewListAction("endpoints", c.Namespace, opts), &api.EndpointsList{}) + if obj == nil { + return nil, err + } + + return obj.(*api.EndpointsList), err +} + +func (c *FakeEndpoints) Create(endpoints *api.Endpoints) (*api.Endpoints, error) { + obj, err := c.Fake.Invokes(NewCreateAction("endpoints", c.Namespace, endpoints), endpoints) + if obj == nil { + return nil, err + } + + return obj.(*api.Endpoints), err +} + +func (c *FakeEndpoints) Update(endpoints *api.Endpoints) (*api.Endpoints, error) { + obj, err := c.Fake.Invokes(NewUpdateAction("endpoints", c.Namespace, endpoints), endpoints) + if obj == nil { + return nil, err + } + + return obj.(*api.Endpoints), err +} + +func (c *FakeEndpoints) Delete(name string) error { + _, err := c.Fake.Invokes(NewDeleteAction("endpoints", c.Namespace, name), &api.Endpoints{}) + return err +} + +func (c *FakeEndpoints) Watch(opts api.ListOptions) (watch.Interface, error) { + return c.Fake.InvokesWatch(NewWatchAction("endpoints", c.Namespace, opts)) +} diff --git a/ingress/vendor/k8s.io/kubernetes/pkg/client/unversioned/testclient/fake_events.go b/ingress/vendor/k8s.io/kubernetes/pkg/client/unversioned/testclient/fake_events.go new file mode 100644 index 0000000000..3da2143fc4 --- /dev/null +++ b/ingress/vendor/k8s.io/kubernetes/pkg/client/unversioned/testclient/fake_events.go @@ -0,0 +1,151 @@ +/* +Copyright 2014 The Kubernetes Authors All rights reserved. + +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 testclient + +import ( + "k8s.io/kubernetes/pkg/api" + "k8s.io/kubernetes/pkg/fields" + "k8s.io/kubernetes/pkg/runtime" + "k8s.io/kubernetes/pkg/watch" +) + +// FakeEvents implements EventInterface. Meant to be embedded into a struct to get a default +// implementation. This makes faking out just the method you want to test easier. +type FakeEvents struct { + Fake *Fake + Namespace string +} + +// Get returns the given event, or an error. +func (c *FakeEvents) Get(name string) (*api.Event, error) { + action := NewRootGetAction("events", name) + if c.Namespace != "" { + action = NewGetAction("events", c.Namespace, name) + } + obj, err := c.Fake.Invokes(action, &api.Event{}) + if obj == nil { + return nil, err + } + + return obj.(*api.Event), err +} + +// List returns a list of events matching the selectors. +func (c *FakeEvents) List(opts api.ListOptions) (*api.EventList, error) { + action := NewRootListAction("events", opts) + if c.Namespace != "" { + action = NewListAction("events", c.Namespace, opts) + } + obj, err := c.Fake.Invokes(action, &api.EventList{}) + if obj == nil { + return nil, err + } + + return obj.(*api.EventList), err +} + +// Create makes a new event. Returns the copy of the event the server returns, or an error. +func (c *FakeEvents) Create(event *api.Event) (*api.Event, error) { + action := NewRootCreateAction("events", event) + if c.Namespace != "" { + action = NewCreateAction("events", c.Namespace, event) + } + obj, err := c.Fake.Invokes(action, event) + if obj == nil { + return nil, err + } + + return obj.(*api.Event), err +} + +// Update replaces an existing event. Returns the copy of the event the server returns, or an error. +func (c *FakeEvents) Update(event *api.Event) (*api.Event, error) { + action := NewRootUpdateAction("events", event) + if c.Namespace != "" { + action = NewUpdateAction("events", c.Namespace, event) + } + obj, err := c.Fake.Invokes(action, event) + if obj == nil { + return nil, err + } + + return obj.(*api.Event), err +} + +// Patch patches an existing event. Returns the copy of the event the server returns, or an error. +func (c *FakeEvents) Patch(event *api.Event, data []byte) (*api.Event, error) { + action := NewRootPatchAction("events", event) + if c.Namespace != "" { + action = NewPatchAction("events", c.Namespace, event) + } + obj, err := c.Fake.Invokes(action, event) + if obj == nil { + return nil, err + } + + return obj.(*api.Event), err +} + +func (c *FakeEvents) Delete(name string) error { + action := NewRootDeleteAction("events", name) + if c.Namespace != "" { + action = NewDeleteAction("events", c.Namespace, name) + } + _, err := c.Fake.Invokes(action, &api.Event{}) + return err +} + +func (c *FakeEvents) DeleteCollection(options *api.DeleteOptions, listOptions api.ListOptions) error { + action := NewRootDeleteCollectionAction("events", listOptions) + if c.Namespace != "" { + action = NewDeleteCollectionAction("events", c.Namespace, listOptions) + } + _, err := c.Fake.Invokes(action, &api.EventList{}) + return err +} + +// Watch starts watching for events matching the given selectors. +func (c *FakeEvents) Watch(opts api.ListOptions) (watch.Interface, error) { + action := NewRootWatchAction("events", opts) + if c.Namespace != "" { + action = NewWatchAction("events", c.Namespace, opts) + } + return c.Fake.InvokesWatch(action) +} + +// Search returns a list of events matching the specified object. +func (c *FakeEvents) Search(objOrRef runtime.Object) (*api.EventList, error) { + action := NewRootListAction("events", api.ListOptions{}) + if c.Namespace != "" { + action = NewListAction("events", c.Namespace, api.ListOptions{}) + } + obj, err := c.Fake.Invokes(action, &api.EventList{}) + if obj == nil { + return nil, err + } + + return obj.(*api.EventList), err +} + +func (c *FakeEvents) GetFieldSelector(involvedObjectName, involvedObjectNamespace, involvedObjectKind, involvedObjectUID *string) fields.Selector { + action := GenericActionImpl{} + action.Verb = "get-field-selector" + action.Resource = "events" + + c.Fake.Invokes(action, nil) + return fields.Everything() +} diff --git a/ingress/vendor/k8s.io/kubernetes/pkg/client/unversioned/testclient/fake_horizontal_pod_autoscalers.go b/ingress/vendor/k8s.io/kubernetes/pkg/client/unversioned/testclient/fake_horizontal_pod_autoscalers.go new file mode 100644 index 0000000000..e50b326d91 --- /dev/null +++ b/ingress/vendor/k8s.io/kubernetes/pkg/client/unversioned/testclient/fake_horizontal_pod_autoscalers.go @@ -0,0 +1,164 @@ +/* +Copyright 2015 The Kubernetes Authors All rights reserved. + +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 testclient + +import ( + "k8s.io/kubernetes/pkg/api" + "k8s.io/kubernetes/pkg/apis/extensions" + "k8s.io/kubernetes/pkg/labels" + "k8s.io/kubernetes/pkg/watch" +) + +// FakeHorizontalPodAutoscalers implements HorizontalPodAutoscalerInterface. Meant to be embedded into a struct to get a default +// implementation. This makes faking out just the methods you want to test easier. +type FakeHorizontalPodAutoscalers struct { + Fake *FakeExperimental + Namespace string +} + +func (c *FakeHorizontalPodAutoscalers) Get(name string) (*extensions.HorizontalPodAutoscaler, error) { + obj, err := c.Fake.Invokes(NewGetAction("horizontalpodautoscalers", c.Namespace, name), &extensions.HorizontalPodAutoscaler{}) + if obj == nil { + return nil, err + } + + return obj.(*extensions.HorizontalPodAutoscaler), err +} + +func (c *FakeHorizontalPodAutoscalers) List(opts api.ListOptions) (*extensions.HorizontalPodAutoscalerList, error) { + obj, err := c.Fake.Invokes(NewListAction("horizontalpodautoscalers", c.Namespace, opts), &extensions.HorizontalPodAutoscalerList{}) + if obj == nil { + return nil, err + } + label := opts.LabelSelector + if label == nil { + label = labels.Everything() + } + list := &extensions.HorizontalPodAutoscalerList{} + for _, a := range obj.(*extensions.HorizontalPodAutoscalerList).Items { + if label.Matches(labels.Set(a.Labels)) { + list.Items = append(list.Items, a) + } + } + return list, err +} + +func (c *FakeHorizontalPodAutoscalers) Create(a *extensions.HorizontalPodAutoscaler) (*extensions.HorizontalPodAutoscaler, error) { + obj, err := c.Fake.Invokes(NewCreateAction("horizontalpodautoscalers", c.Namespace, a), a) + if obj == nil { + return nil, err + } + + return obj.(*extensions.HorizontalPodAutoscaler), err +} + +func (c *FakeHorizontalPodAutoscalers) Update(a *extensions.HorizontalPodAutoscaler) (*extensions.HorizontalPodAutoscaler, error) { + obj, err := c.Fake.Invokes(NewUpdateAction("horizontalpodautoscalers", c.Namespace, a), a) + if obj == nil { + return nil, err + } + + return obj.(*extensions.HorizontalPodAutoscaler), err +} + +func (c *FakeHorizontalPodAutoscalers) UpdateStatus(a *extensions.HorizontalPodAutoscaler) (*extensions.HorizontalPodAutoscaler, error) { + obj, err := c.Fake.Invokes(NewUpdateSubresourceAction("horizontalpodautoscalers", "status", c.Namespace, a), &extensions.HorizontalPodAutoscaler{}) + if obj == nil { + return nil, err + } + return obj.(*extensions.HorizontalPodAutoscaler), err +} + +func (c *FakeHorizontalPodAutoscalers) Delete(name string, options *api.DeleteOptions) error { + _, err := c.Fake.Invokes(NewDeleteAction("horizontalpodautoscalers", c.Namespace, name), &extensions.HorizontalPodAutoscaler{}) + return err +} + +func (c *FakeHorizontalPodAutoscalers) Watch(opts api.ListOptions) (watch.Interface, error) { + return c.Fake.InvokesWatch(NewWatchAction("horizontalpodautoscalers", c.Namespace, opts)) +} + +// FakeHorizontalPodAutoscalers implements HorizontalPodAutoscalerInterface. Meant to be embedded into a struct to get a default +// implementation. This makes faking out just the methods you want to test easier. +// This is a test implementation of HorizontalPodAutoscalersV1 +// TODO(piosz): get back to one client implementation once HPA will be graduated to GA completely +type FakeHorizontalPodAutoscalersV1 struct { + Fake *FakeAutoscaling + Namespace string +} + +func (c *FakeHorizontalPodAutoscalersV1) Get(name string) (*extensions.HorizontalPodAutoscaler, error) { + obj, err := c.Fake.Invokes(NewGetAction("horizontalpodautoscalers", c.Namespace, name), &extensions.HorizontalPodAutoscaler{}) + if obj == nil { + return nil, err + } + + return obj.(*extensions.HorizontalPodAutoscaler), err +} + +func (c *FakeHorizontalPodAutoscalersV1) List(opts api.ListOptions) (*extensions.HorizontalPodAutoscalerList, error) { + obj, err := c.Fake.Invokes(NewListAction("horizontalpodautoscalers", c.Namespace, opts), &extensions.HorizontalPodAutoscalerList{}) + if obj == nil { + return nil, err + } + label := opts.LabelSelector + if label == nil { + label = labels.Everything() + } + list := &extensions.HorizontalPodAutoscalerList{} + for _, a := range obj.(*extensions.HorizontalPodAutoscalerList).Items { + if label.Matches(labels.Set(a.Labels)) { + list.Items = append(list.Items, a) + } + } + return list, err +} + +func (c *FakeHorizontalPodAutoscalersV1) Create(a *extensions.HorizontalPodAutoscaler) (*extensions.HorizontalPodAutoscaler, error) { + obj, err := c.Fake.Invokes(NewCreateAction("horizontalpodautoscalers", c.Namespace, a), a) + if obj == nil { + return nil, err + } + + return obj.(*extensions.HorizontalPodAutoscaler), err +} + +func (c *FakeHorizontalPodAutoscalersV1) Update(a *extensions.HorizontalPodAutoscaler) (*extensions.HorizontalPodAutoscaler, error) { + obj, err := c.Fake.Invokes(NewUpdateAction("horizontalpodautoscalers", c.Namespace, a), a) + if obj == nil { + return nil, err + } + + return obj.(*extensions.HorizontalPodAutoscaler), err +} + +func (c *FakeHorizontalPodAutoscalersV1) UpdateStatus(a *extensions.HorizontalPodAutoscaler) (*extensions.HorizontalPodAutoscaler, error) { + obj, err := c.Fake.Invokes(NewUpdateSubresourceAction("horizontalpodautoscalers", "status", c.Namespace, a), &extensions.HorizontalPodAutoscaler{}) + if obj == nil { + return nil, err + } + return obj.(*extensions.HorizontalPodAutoscaler), err +} + +func (c *FakeHorizontalPodAutoscalersV1) Delete(name string, options *api.DeleteOptions) error { + _, err := c.Fake.Invokes(NewDeleteAction("horizontalpodautoscalers", c.Namespace, name), &extensions.HorizontalPodAutoscaler{}) + return err +} + +func (c *FakeHorizontalPodAutoscalersV1) Watch(opts api.ListOptions) (watch.Interface, error) { + return c.Fake.InvokesWatch(NewWatchAction("horizontalpodautoscalers", c.Namespace, opts)) +} diff --git a/ingress/vendor/k8s.io/kubernetes/pkg/client/unversioned/testclient/fake_ingress.go b/ingress/vendor/k8s.io/kubernetes/pkg/client/unversioned/testclient/fake_ingress.go new file mode 100644 index 0000000000..b15458997f --- /dev/null +++ b/ingress/vendor/k8s.io/kubernetes/pkg/client/unversioned/testclient/fake_ingress.go @@ -0,0 +1,84 @@ +/* +Copyright 2015 The Kubernetes Authors All rights reserved. + +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 testclient + +import ( + "k8s.io/kubernetes/pkg/api" + "k8s.io/kubernetes/pkg/apis/extensions" + "k8s.io/kubernetes/pkg/watch" +) + +// FakeIngress implements IngressInterface. Meant to be embedded into a struct to get a default +// implementation. This makes faking out just the method you want to test easier. +type FakeIngress struct { + Fake *FakeExperimental + Namespace string +} + +func (c *FakeIngress) Get(name string) (*extensions.Ingress, error) { + obj, err := c.Fake.Invokes(NewGetAction("ingresses", c.Namespace, name), &extensions.Ingress{}) + if obj == nil { + return nil, err + } + + return obj.(*extensions.Ingress), err +} + +func (c *FakeIngress) List(opts api.ListOptions) (*extensions.IngressList, error) { + obj, err := c.Fake.Invokes(NewListAction("ingresses", c.Namespace, opts), &extensions.IngressList{}) + if obj == nil { + return nil, err + } + + return obj.(*extensions.IngressList), err +} + +func (c *FakeIngress) Create(ingress *extensions.Ingress) (*extensions.Ingress, error) { + obj, err := c.Fake.Invokes(NewCreateAction("ingresses", c.Namespace, ingress), ingress) + if obj == nil { + return nil, err + } + + return obj.(*extensions.Ingress), err +} + +func (c *FakeIngress) Update(ingress *extensions.Ingress) (*extensions.Ingress, error) { + obj, err := c.Fake.Invokes(NewUpdateAction("ingresses", c.Namespace, ingress), ingress) + if obj == nil { + return nil, err + } + + return obj.(*extensions.Ingress), err +} + +func (c *FakeIngress) Delete(name string, options *api.DeleteOptions) error { + _, err := c.Fake.Invokes(NewDeleteAction("ingresses", c.Namespace, name), &extensions.Ingress{}) + return err +} + +func (c *FakeIngress) Watch(opts api.ListOptions) (watch.Interface, error) { + return c.Fake.InvokesWatch(NewWatchAction("ingresses", c.Namespace, opts)) +} + +func (c *FakeIngress) UpdateStatus(ingress *extensions.Ingress) (result *extensions.Ingress, err error) { + obj, err := c.Fake.Invokes(NewUpdateSubresourceAction("ingresses", "status", c.Namespace, ingress), ingress) + if obj == nil { + return nil, err + } + + return obj.(*extensions.Ingress), err +} diff --git a/ingress/vendor/k8s.io/kubernetes/pkg/client/unversioned/testclient/fake_jobs.go b/ingress/vendor/k8s.io/kubernetes/pkg/client/unversioned/testclient/fake_jobs.go new file mode 100644 index 0000000000..dedde9dc3d --- /dev/null +++ b/ingress/vendor/k8s.io/kubernetes/pkg/client/unversioned/testclient/fake_jobs.go @@ -0,0 +1,147 @@ +/* +Copyright 2015 The Kubernetes Authors All rights reserved. + +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 testclient + +import ( + "k8s.io/kubernetes/pkg/api" + "k8s.io/kubernetes/pkg/apis/batch" + "k8s.io/kubernetes/pkg/watch" +) + +// FakeJobs implements JobInterface. Meant to be embedded into a struct to get a default +// implementation. This makes faking out just the method you want to test easier. +type FakeJobs struct { + Fake *FakeExperimental + Namespace string +} + +func (c *FakeJobs) Get(name string) (*batch.Job, error) { + obj, err := c.Fake.Invokes(NewGetAction("jobs", c.Namespace, name), &batch.Job{}) + if obj == nil { + return nil, err + } + + return obj.(*batch.Job), err +} + +func (c *FakeJobs) List(opts api.ListOptions) (*batch.JobList, error) { + obj, err := c.Fake.Invokes(NewListAction("jobs", c.Namespace, opts), &batch.JobList{}) + if obj == nil { + return nil, err + } + + return obj.(*batch.JobList), err +} + +func (c *FakeJobs) Create(job *batch.Job) (*batch.Job, error) { + obj, err := c.Fake.Invokes(NewCreateAction("jobs", c.Namespace, job), job) + if obj == nil { + return nil, err + } + + return obj.(*batch.Job), err +} + +func (c *FakeJobs) Update(job *batch.Job) (*batch.Job, error) { + obj, err := c.Fake.Invokes(NewUpdateAction("jobs", c.Namespace, job), job) + if obj == nil { + return nil, err + } + + return obj.(*batch.Job), err +} + +func (c *FakeJobs) Delete(name string, options *api.DeleteOptions) error { + _, err := c.Fake.Invokes(NewDeleteAction("jobs", c.Namespace, name), &batch.Job{}) + return err +} + +func (c *FakeJobs) Watch(opts api.ListOptions) (watch.Interface, error) { + return c.Fake.InvokesWatch(NewWatchAction("jobs", c.Namespace, opts)) +} + +func (c *FakeJobs) UpdateStatus(job *batch.Job) (result *batch.Job, err error) { + obj, err := c.Fake.Invokes(NewUpdateSubresourceAction("jobs", "status", c.Namespace, job), job) + if obj == nil { + return nil, err + } + + return obj.(*batch.Job), err +} + +// FakeJobs implements JobInterface. Meant to be embedded into a struct to get a default +// implementation. This makes faking out just the methods you want to test easier. +// This is a test implementation of JobsV1 +// TODO(piosz): get back to one client implementation once HPA will be graduated to GA completely +type FakeJobsV1 struct { + Fake *FakeBatch + Namespace string +} + +func (c *FakeJobsV1) Get(name string) (*batch.Job, error) { + obj, err := c.Fake.Invokes(NewGetAction("jobs", c.Namespace, name), &batch.Job{}) + if obj == nil { + return nil, err + } + + return obj.(*batch.Job), err +} + +func (c *FakeJobsV1) List(opts api.ListOptions) (*batch.JobList, error) { + obj, err := c.Fake.Invokes(NewListAction("jobs", c.Namespace, opts), &batch.JobList{}) + if obj == nil { + return nil, err + } + + return obj.(*batch.JobList), err +} + +func (c *FakeJobsV1) Create(job *batch.Job) (*batch.Job, error) { + obj, err := c.Fake.Invokes(NewCreateAction("jobs", c.Namespace, job), job) + if obj == nil { + return nil, err + } + + return obj.(*batch.Job), err +} + +func (c *FakeJobsV1) Update(job *batch.Job) (*batch.Job, error) { + obj, err := c.Fake.Invokes(NewUpdateAction("jobs", c.Namespace, job), job) + if obj == nil { + return nil, err + } + + return obj.(*batch.Job), err +} + +func (c *FakeJobsV1) Delete(name string, options *api.DeleteOptions) error { + _, err := c.Fake.Invokes(NewDeleteAction("jobs", c.Namespace, name), &batch.Job{}) + return err +} + +func (c *FakeJobsV1) Watch(opts api.ListOptions) (watch.Interface, error) { + return c.Fake.InvokesWatch(NewWatchAction("jobs", c.Namespace, opts)) +} + +func (c *FakeJobsV1) UpdateStatus(job *batch.Job) (result *batch.Job, err error) { + obj, err := c.Fake.Invokes(NewUpdateSubresourceAction("jobs", "status", c.Namespace, job), job) + if obj == nil { + return nil, err + } + + return obj.(*batch.Job), err +} diff --git a/ingress/vendor/k8s.io/kubernetes/pkg/client/unversioned/testclient/fake_limit_ranges.go b/ingress/vendor/k8s.io/kubernetes/pkg/client/unversioned/testclient/fake_limit_ranges.go new file mode 100644 index 0000000000..3669f5ff82 --- /dev/null +++ b/ingress/vendor/k8s.io/kubernetes/pkg/client/unversioned/testclient/fake_limit_ranges.go @@ -0,0 +1,74 @@ +/* +Copyright 2014 The Kubernetes Authors All rights reserved. + +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 testclient + +import ( + "k8s.io/kubernetes/pkg/api" + "k8s.io/kubernetes/pkg/watch" +) + +// FakeLimitRanges implements PodsInterface. Meant to be embedded into a struct to get a default +// implementation. This makes faking out just the methods you want to test easier. +type FakeLimitRanges struct { + Fake *Fake + Namespace string +} + +func (c *FakeLimitRanges) Get(name string) (*api.LimitRange, error) { + obj, err := c.Fake.Invokes(NewGetAction("limitranges", c.Namespace, name), &api.LimitRange{}) + if obj == nil { + return nil, err + } + + return obj.(*api.LimitRange), err +} + +func (c *FakeLimitRanges) List(opts api.ListOptions) (*api.LimitRangeList, error) { + obj, err := c.Fake.Invokes(NewListAction("limitranges", c.Namespace, opts), &api.LimitRangeList{}) + if obj == nil { + return nil, err + } + + return obj.(*api.LimitRangeList), err +} + +func (c *FakeLimitRanges) Create(limitRange *api.LimitRange) (*api.LimitRange, error) { + obj, err := c.Fake.Invokes(NewCreateAction("limitranges", c.Namespace, limitRange), limitRange) + if obj == nil { + return nil, err + } + + return obj.(*api.LimitRange), err +} + +func (c *FakeLimitRanges) Update(limitRange *api.LimitRange) (*api.LimitRange, error) { + obj, err := c.Fake.Invokes(NewUpdateAction("limitranges", c.Namespace, limitRange), limitRange) + if obj == nil { + return nil, err + } + + return obj.(*api.LimitRange), err +} + +func (c *FakeLimitRanges) Delete(name string) error { + _, err := c.Fake.Invokes(NewDeleteAction("limitranges", c.Namespace, name), &api.LimitRange{}) + return err +} + +func (c *FakeLimitRanges) Watch(opts api.ListOptions) (watch.Interface, error) { + return c.Fake.InvokesWatch(NewWatchAction("limitranges", c.Namespace, opts)) +} diff --git a/ingress/vendor/k8s.io/kubernetes/pkg/client/unversioned/testclient/fake_namespaces.go b/ingress/vendor/k8s.io/kubernetes/pkg/client/unversioned/testclient/fake_namespaces.go new file mode 100644 index 0000000000..8c4ac1ac27 --- /dev/null +++ b/ingress/vendor/k8s.io/kubernetes/pkg/client/unversioned/testclient/fake_namespaces.go @@ -0,0 +1,103 @@ +/* +Copyright 2014 The Kubernetes Authors All rights reserved. + +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 testclient + +import ( + "k8s.io/kubernetes/pkg/api" + "k8s.io/kubernetes/pkg/watch" +) + +// FakeNamespaces implements NamespacesInterface. Meant to be embedded into a struct to get a default +// implementation. This makes faking out just the methods you want to test easier. +type FakeNamespaces struct { + Fake *Fake +} + +func (c *FakeNamespaces) Get(name string) (*api.Namespace, error) { + obj, err := c.Fake.Invokes(NewRootGetAction("namespaces", name), &api.Namespace{}) + if obj == nil { + return nil, err + } + + return obj.(*api.Namespace), err +} + +func (c *FakeNamespaces) List(opts api.ListOptions) (*api.NamespaceList, error) { + obj, err := c.Fake.Invokes(NewRootListAction("namespaces", opts), &api.NamespaceList{}) + if obj == nil { + return nil, err + } + + return obj.(*api.NamespaceList), err +} + +func (c *FakeNamespaces) Create(namespace *api.Namespace) (*api.Namespace, error) { + obj, err := c.Fake.Invokes(NewRootCreateAction("namespaces", namespace), namespace) + if obj == nil { + return nil, err + } + + return obj.(*api.Namespace), err +} + +func (c *FakeNamespaces) Update(namespace *api.Namespace) (*api.Namespace, error) { + obj, err := c.Fake.Invokes(NewRootUpdateAction("namespaces", namespace), namespace) + if obj == nil { + return nil, err + } + + return obj.(*api.Namespace), err +} + +func (c *FakeNamespaces) Delete(name string) error { + _, err := c.Fake.Invokes(NewRootDeleteAction("namespaces", name), &api.Namespace{}) + return err +} + +func (c *FakeNamespaces) Watch(opts api.ListOptions) (watch.Interface, error) { + return c.Fake.InvokesWatch(NewRootWatchAction("namespaces", opts)) +} + +func (c *FakeNamespaces) Finalize(namespace *api.Namespace) (*api.Namespace, error) { + action := CreateActionImpl{} + action.Verb = "create" + action.Resource = "namespaces" + action.Subresource = "finalize" + action.Object = namespace + + obj, err := c.Fake.Invokes(action, namespace) + if obj == nil { + return nil, err + } + + return obj.(*api.Namespace), err +} + +func (c *FakeNamespaces) Status(namespace *api.Namespace) (*api.Namespace, error) { + action := CreateActionImpl{} + action.Verb = "create" + action.Resource = "namespaces" + action.Subresource = "status" + action.Object = namespace + + obj, err := c.Fake.Invokes(action, namespace) + if obj == nil { + return nil, err + } + + return obj.(*api.Namespace), err +} diff --git a/ingress/vendor/k8s.io/kubernetes/pkg/client/unversioned/testclient/fake_nodes.go b/ingress/vendor/k8s.io/kubernetes/pkg/client/unversioned/testclient/fake_nodes.go new file mode 100644 index 0000000000..b1943366e5 --- /dev/null +++ b/ingress/vendor/k8s.io/kubernetes/pkg/client/unversioned/testclient/fake_nodes.go @@ -0,0 +1,88 @@ +/* +Copyright 2014 The Kubernetes Authors All rights reserved. + +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 testclient + +import ( + "k8s.io/kubernetes/pkg/api" + "k8s.io/kubernetes/pkg/watch" +) + +// FakeNodes implements NodeInterface. Meant to be embedded into a struct to get a default +// implementation. This makes faking out just the method you want to test easier. +type FakeNodes struct { + Fake *Fake +} + +func (c *FakeNodes) Get(name string) (*api.Node, error) { + obj, err := c.Fake.Invokes(NewRootGetAction("nodes", name), &api.Node{}) + if obj == nil { + return nil, err + } + + return obj.(*api.Node), err +} + +func (c *FakeNodes) List(opts api.ListOptions) (*api.NodeList, error) { + obj, err := c.Fake.Invokes(NewRootListAction("nodes", opts), &api.NodeList{}) + if obj == nil { + return nil, err + } + + return obj.(*api.NodeList), err +} + +func (c *FakeNodes) Create(node *api.Node) (*api.Node, error) { + obj, err := c.Fake.Invokes(NewRootCreateAction("nodes", node), node) + if obj == nil { + return nil, err + } + + return obj.(*api.Node), err +} + +func (c *FakeNodes) Update(node *api.Node) (*api.Node, error) { + obj, err := c.Fake.Invokes(NewRootUpdateAction("nodes", node), node) + if obj == nil { + return nil, err + } + + return obj.(*api.Node), err +} + +func (c *FakeNodes) Delete(name string) error { + _, err := c.Fake.Invokes(NewRootDeleteAction("nodes", name), &api.Node{}) + return err +} + +func (c *FakeNodes) Watch(opts api.ListOptions) (watch.Interface, error) { + return c.Fake.InvokesWatch(NewRootWatchAction("nodes", opts)) +} + +func (c *FakeNodes) UpdateStatus(node *api.Node) (*api.Node, error) { + action := CreateActionImpl{} + action.Verb = "update" + action.Resource = "nodes" + action.Subresource = "status" + action.Object = node + + obj, err := c.Fake.Invokes(action, node) + if obj == nil { + return nil, err + } + + return obj.(*api.Node), err +} diff --git a/ingress/vendor/k8s.io/kubernetes/pkg/client/unversioned/testclient/fake_persistent_volume_claims.go b/ingress/vendor/k8s.io/kubernetes/pkg/client/unversioned/testclient/fake_persistent_volume_claims.go new file mode 100644 index 0000000000..cadfb084c3 --- /dev/null +++ b/ingress/vendor/k8s.io/kubernetes/pkg/client/unversioned/testclient/fake_persistent_volume_claims.go @@ -0,0 +1,81 @@ +/* +Copyright 2014 The Kubernetes Authors All rights reserved. + +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 testclient + +import ( + "k8s.io/kubernetes/pkg/api" + "k8s.io/kubernetes/pkg/watch" +) + +type FakePersistentVolumeClaims struct { + Fake *Fake + Namespace string +} + +func (c *FakePersistentVolumeClaims) Get(name string) (*api.PersistentVolumeClaim, error) { + obj, err := c.Fake.Invokes(NewGetAction("persistentvolumeclaims", c.Namespace, name), &api.PersistentVolumeClaim{}) + if obj == nil { + return nil, err + } + + return obj.(*api.PersistentVolumeClaim), err +} + +func (c *FakePersistentVolumeClaims) List(opts api.ListOptions) (*api.PersistentVolumeClaimList, error) { + obj, err := c.Fake.Invokes(NewListAction("persistentvolumeclaims", c.Namespace, opts), &api.PersistentVolumeClaimList{}) + if obj == nil { + return nil, err + } + + return obj.(*api.PersistentVolumeClaimList), err +} + +func (c *FakePersistentVolumeClaims) Create(claim *api.PersistentVolumeClaim) (*api.PersistentVolumeClaim, error) { + obj, err := c.Fake.Invokes(NewCreateAction("persistentvolumeclaims", c.Namespace, claim), claim) + if obj == nil { + return nil, err + } + + return obj.(*api.PersistentVolumeClaim), err +} + +func (c *FakePersistentVolumeClaims) Update(claim *api.PersistentVolumeClaim) (*api.PersistentVolumeClaim, error) { + obj, err := c.Fake.Invokes(NewUpdateAction("persistentvolumeclaims", c.Namespace, claim), claim) + if obj == nil { + return nil, err + } + + return obj.(*api.PersistentVolumeClaim), err +} + +func (c *FakePersistentVolumeClaims) Delete(name string) error { + _, err := c.Fake.Invokes(NewDeleteAction("persistentvolumeclaims", c.Namespace, name), &api.PersistentVolumeClaim{}) + return err +} + +func (c *FakePersistentVolumeClaims) Watch(opts api.ListOptions) (watch.Interface, error) { + return c.Fake.InvokesWatch(NewWatchAction("persistentvolumeclaims", c.Namespace, opts)) +} + +func (c *FakePersistentVolumeClaims) UpdateStatus(claim *api.PersistentVolumeClaim) (*api.PersistentVolumeClaim, error) { + obj, err := c.Fake.Invokes(NewUpdateSubresourceAction("persistentvolumeclaims", "status", c.Namespace, claim), claim) + if obj == nil { + return nil, err + } + + return obj.(*api.PersistentVolumeClaim), err +} diff --git a/ingress/vendor/k8s.io/kubernetes/pkg/client/unversioned/testclient/fake_persistent_volumes.go b/ingress/vendor/k8s.io/kubernetes/pkg/client/unversioned/testclient/fake_persistent_volumes.go new file mode 100644 index 0000000000..cb184bc441 --- /dev/null +++ b/ingress/vendor/k8s.io/kubernetes/pkg/client/unversioned/testclient/fake_persistent_volumes.go @@ -0,0 +1,86 @@ +/* +Copyright 2014 The Kubernetes Authors All rights reserved. + +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 testclient + +import ( + "k8s.io/kubernetes/pkg/api" + "k8s.io/kubernetes/pkg/watch" +) + +type FakePersistentVolumes struct { + Fake *Fake +} + +func (c *FakePersistentVolumes) Get(name string) (*api.PersistentVolume, error) { + obj, err := c.Fake.Invokes(NewRootGetAction("persistentvolumes", name), &api.PersistentVolume{}) + if obj == nil { + return nil, err + } + + return obj.(*api.PersistentVolume), err +} + +func (c *FakePersistentVolumes) List(opts api.ListOptions) (*api.PersistentVolumeList, error) { + obj, err := c.Fake.Invokes(NewRootListAction("persistentvolumes", opts), &api.PersistentVolumeList{}) + if obj == nil { + return nil, err + } + + return obj.(*api.PersistentVolumeList), err +} + +func (c *FakePersistentVolumes) Create(pv *api.PersistentVolume) (*api.PersistentVolume, error) { + obj, err := c.Fake.Invokes(NewRootCreateAction("persistentvolumes", pv), pv) + if obj == nil { + return nil, err + } + + return obj.(*api.PersistentVolume), err +} + +func (c *FakePersistentVolumes) Update(pv *api.PersistentVolume) (*api.PersistentVolume, error) { + obj, err := c.Fake.Invokes(NewRootUpdateAction("persistentvolumes", pv), pv) + if obj == nil { + return nil, err + } + + return obj.(*api.PersistentVolume), err +} + +func (c *FakePersistentVolumes) Delete(name string) error { + _, err := c.Fake.Invokes(NewRootDeleteAction("persistentvolumes", name), &api.PersistentVolume{}) + return err +} + +func (c *FakePersistentVolumes) Watch(opts api.ListOptions) (watch.Interface, error) { + return c.Fake.InvokesWatch(NewRootWatchAction("persistentvolumes", opts)) +} + +func (c *FakePersistentVolumes) UpdateStatus(pv *api.PersistentVolume) (*api.PersistentVolume, error) { + action := UpdateActionImpl{} + action.Verb = "update" + action.Resource = "persistentvolumes" + action.Subresource = "status" + action.Object = pv + + obj, err := c.Fake.Invokes(action, pv) + if obj == nil { + return nil, err + } + + return obj.(*api.PersistentVolume), err +} diff --git a/ingress/vendor/k8s.io/kubernetes/pkg/client/unversioned/testclient/fake_pod_templates.go b/ingress/vendor/k8s.io/kubernetes/pkg/client/unversioned/testclient/fake_pod_templates.go new file mode 100644 index 0000000000..47ff3d8ace --- /dev/null +++ b/ingress/vendor/k8s.io/kubernetes/pkg/client/unversioned/testclient/fake_pod_templates.go @@ -0,0 +1,74 @@ +/* +Copyright 2015 The Kubernetes Authors All rights reserved. + +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 testclient + +import ( + "k8s.io/kubernetes/pkg/api" + "k8s.io/kubernetes/pkg/watch" +) + +// FakePodTemplates implements PodTemplatesInterface. Meant to be embedded into a struct to get a default +// implementation. This makes faking out just the methods you want to test easier. +type FakePodTemplates struct { + Fake *Fake + Namespace string +} + +func (c *FakePodTemplates) Get(name string) (*api.PodTemplate, error) { + obj, err := c.Fake.Invokes(NewGetAction("podtemplates", c.Namespace, name), &api.PodTemplate{}) + if obj == nil { + return nil, err + } + + return obj.(*api.PodTemplate), err +} + +func (c *FakePodTemplates) List(opts api.ListOptions) (*api.PodTemplateList, error) { + obj, err := c.Fake.Invokes(NewListAction("podtemplates", c.Namespace, opts), &api.PodTemplateList{}) + if obj == nil { + return nil, err + } + + return obj.(*api.PodTemplateList), err +} + +func (c *FakePodTemplates) Create(pod *api.PodTemplate) (*api.PodTemplate, error) { + obj, err := c.Fake.Invokes(NewCreateAction("podtemplates", c.Namespace, pod), pod) + if obj == nil { + return nil, err + } + + return obj.(*api.PodTemplate), err +} + +func (c *FakePodTemplates) Update(pod *api.PodTemplate) (*api.PodTemplate, error) { + obj, err := c.Fake.Invokes(NewUpdateAction("podtemplates", c.Namespace, pod), pod) + if obj == nil { + return nil, err + } + + return obj.(*api.PodTemplate), err +} + +func (c *FakePodTemplates) Delete(name string, options *api.DeleteOptions) error { + _, err := c.Fake.Invokes(NewDeleteAction("podtemplates", c.Namespace, name), &api.PodTemplate{}) + return err +} + +func (c *FakePodTemplates) Watch(opts api.ListOptions) (watch.Interface, error) { + return c.Fake.InvokesWatch(NewWatchAction("podtemplates", c.Namespace, opts)) +} diff --git a/ingress/vendor/k8s.io/kubernetes/pkg/client/unversioned/testclient/fake_pods.go b/ingress/vendor/k8s.io/kubernetes/pkg/client/unversioned/testclient/fake_pods.go new file mode 100644 index 0000000000..e634030c80 --- /dev/null +++ b/ingress/vendor/k8s.io/kubernetes/pkg/client/unversioned/testclient/fake_pods.go @@ -0,0 +1,117 @@ +/* +Copyright 2014 The Kubernetes Authors All rights reserved. + +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 testclient + +import ( + "k8s.io/kubernetes/pkg/api" + "k8s.io/kubernetes/pkg/client/restclient" + "k8s.io/kubernetes/pkg/labels" + "k8s.io/kubernetes/pkg/watch" +) + +// FakePods implements PodsInterface. Meant to be embedded into a struct to get a default +// implementation. This makes faking out just the methods you want to test easier. +type FakePods struct { + Fake *Fake + Namespace string +} + +func (c *FakePods) Get(name string) (*api.Pod, error) { + obj, err := c.Fake.Invokes(NewGetAction("pods", c.Namespace, name), &api.Pod{}) + if obj == nil { + return nil, err + } + + return obj.(*api.Pod), err +} + +func (c *FakePods) List(opts api.ListOptions) (*api.PodList, error) { + obj, err := c.Fake.Invokes(NewListAction("pods", c.Namespace, opts), &api.PodList{}) + if obj == nil { + return nil, err + } + label := opts.LabelSelector + if label == nil { + label = labels.Everything() + } + list := &api.PodList{} + for _, pod := range obj.(*api.PodList).Items { + if label.Matches(labels.Set(pod.Labels)) { + list.Items = append(list.Items, pod) + } + } + return list, err +} + +func (c *FakePods) Create(pod *api.Pod) (*api.Pod, error) { + obj, err := c.Fake.Invokes(NewCreateAction("pods", c.Namespace, pod), pod) + if obj == nil { + return nil, err + } + + return obj.(*api.Pod), err +} + +func (c *FakePods) Update(pod *api.Pod) (*api.Pod, error) { + obj, err := c.Fake.Invokes(NewUpdateAction("pods", c.Namespace, pod), pod) + if obj == nil { + return nil, err + } + + return obj.(*api.Pod), err +} + +func (c *FakePods) Delete(name string, options *api.DeleteOptions) error { + _, err := c.Fake.Invokes(NewDeleteAction("pods", c.Namespace, name), &api.Pod{}) + return err +} + +func (c *FakePods) Watch(opts api.ListOptions) (watch.Interface, error) { + return c.Fake.InvokesWatch(NewWatchAction("pods", c.Namespace, opts)) +} + +func (c *FakePods) Bind(binding *api.Binding) error { + action := CreateActionImpl{} + action.Verb = "create" + action.Resource = "pods" + action.Subresource = "bindings" + action.Object = binding + + _, err := c.Fake.Invokes(action, binding) + return err +} + +func (c *FakePods) UpdateStatus(pod *api.Pod) (*api.Pod, error) { + obj, err := c.Fake.Invokes(NewUpdateSubresourceAction("pods", "status", c.Namespace, pod), pod) + if obj == nil { + return nil, err + } + + return obj.(*api.Pod), err +} + +func (c *FakePods) GetLogs(name string, opts *api.PodLogOptions) *restclient.Request { + action := GenericActionImpl{} + action.Verb = "get" + action.Namespace = c.Namespace + action.Resource = "pod" + action.Subresource = "logs" + action.Value = opts + + _, _ = c.Fake.Invokes(action, &api.Pod{}) + return &restclient.Request{} +} diff --git a/ingress/vendor/k8s.io/kubernetes/pkg/client/unversioned/testclient/fake_podsecuritypolicy.go b/ingress/vendor/k8s.io/kubernetes/pkg/client/unversioned/testclient/fake_podsecuritypolicy.go new file mode 100644 index 0000000000..bb611d322c --- /dev/null +++ b/ingress/vendor/k8s.io/kubernetes/pkg/client/unversioned/testclient/fake_podsecuritypolicy.go @@ -0,0 +1,73 @@ +/* +Copyright 2014 The Kubernetes Authors All rights reserved. + +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 testclient + +import ( + "k8s.io/kubernetes/pkg/api" + "k8s.io/kubernetes/pkg/apis/extensions" + "k8s.io/kubernetes/pkg/watch" +) + +// FakePodSecurityPolicy implements PodSecurityPolicyInterface. Meant to be +// embedded into a struct to get a default implementation. This makes faking out just +// the method you want to test easier. +type FakePodSecurityPolicy struct { + Fake *Fake + Namespace string +} + +func (c *FakePodSecurityPolicy) List(opts api.ListOptions) (*extensions.PodSecurityPolicyList, error) { + obj, err := c.Fake.Invokes(NewListAction("podsecuritypolicies", c.Namespace, opts), &extensions.PodSecurityPolicyList{}) + if obj == nil { + return nil, err + } + + return obj.(*extensions.PodSecurityPolicyList), err +} + +func (c *FakePodSecurityPolicy) Get(name string) (*extensions.PodSecurityPolicy, error) { + obj, err := c.Fake.Invokes(NewGetAction("podsecuritypolicies", c.Namespace, name), &extensions.PodSecurityPolicy{}) + if obj == nil { + return nil, err + } + return obj.(*extensions.PodSecurityPolicy), err +} + +func (c *FakePodSecurityPolicy) Create(scc *extensions.PodSecurityPolicy) (*extensions.PodSecurityPolicy, error) { + obj, err := c.Fake.Invokes(NewCreateAction("podsecuritypolicies", c.Namespace, scc), &extensions.PodSecurityPolicy{}) + if obj == nil { + return nil, err + } + return obj.(*extensions.PodSecurityPolicy), err +} + +func (c *FakePodSecurityPolicy) Update(scc *extensions.PodSecurityPolicy) (*extensions.PodSecurityPolicy, error) { + obj, err := c.Fake.Invokes(NewUpdateAction("podsecuritypolicies", c.Namespace, scc), &extensions.PodSecurityPolicy{}) + if obj == nil { + return nil, err + } + return obj.(*extensions.PodSecurityPolicy), err +} + +func (c *FakePodSecurityPolicy) Delete(name string) error { + _, err := c.Fake.Invokes(NewDeleteAction("podsecuritypolicies", c.Namespace, name), &extensions.PodSecurityPolicy{}) + return err +} + +func (c *FakePodSecurityPolicy) Watch(opts api.ListOptions) (watch.Interface, error) { + return c.Fake.InvokesWatch(NewWatchAction("podsecuritypolicies", c.Namespace, opts)) +} diff --git a/ingress/vendor/k8s.io/kubernetes/pkg/client/unversioned/testclient/fake_replica_sets.go b/ingress/vendor/k8s.io/kubernetes/pkg/client/unversioned/testclient/fake_replica_sets.go new file mode 100644 index 0000000000..29c985c8c9 --- /dev/null +++ b/ingress/vendor/k8s.io/kubernetes/pkg/client/unversioned/testclient/fake_replica_sets.go @@ -0,0 +1,83 @@ +/* +Copyright 2016 The Kubernetes Authors All rights reserved. + +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 testclient + +import ( + "k8s.io/kubernetes/pkg/api" + "k8s.io/kubernetes/pkg/apis/extensions" + "k8s.io/kubernetes/pkg/watch" +) + +// FakeReplicaSets implements ReplicaSetsInterface. Meant to be embedded into a struct to get a default +// implementation. This makes faking out just the method you want to test easier. +type FakeReplicaSets struct { + Fake *FakeExperimental + Namespace string +} + +func (c *FakeReplicaSets) Get(name string) (*extensions.ReplicaSet, error) { + obj, err := c.Fake.Invokes(NewGetAction("replicasets", c.Namespace, name), &extensions.ReplicaSet{}) + if obj == nil { + return nil, err + } + + return obj.(*extensions.ReplicaSet), err +} + +func (c *FakeReplicaSets) List(opts api.ListOptions) (*extensions.ReplicaSetList, error) { + obj, err := c.Fake.Invokes(NewListAction("replicasets", c.Namespace, opts), &extensions.ReplicaSetList{}) + if obj == nil { + return nil, err + } + return obj.(*extensions.ReplicaSetList), err +} + +func (c *FakeReplicaSets) Create(rs *extensions.ReplicaSet) (*extensions.ReplicaSet, error) { + obj, err := c.Fake.Invokes(NewCreateAction("replicasets", c.Namespace, rs), rs) + if obj == nil { + return nil, err + } + + return obj.(*extensions.ReplicaSet), err +} + +func (c *FakeReplicaSets) Update(rs *extensions.ReplicaSet) (*extensions.ReplicaSet, error) { + obj, err := c.Fake.Invokes(NewUpdateAction("replicasets", c.Namespace, rs), rs) + if obj == nil { + return nil, err + } + + return obj.(*extensions.ReplicaSet), err +} + +func (c *FakeReplicaSets) Delete(name string, options *api.DeleteOptions) error { + _, err := c.Fake.Invokes(NewDeleteAction("replicasets", c.Namespace, name), &extensions.ReplicaSet{}) + return err +} + +func (c *FakeReplicaSets) Watch(opts api.ListOptions) (watch.Interface, error) { + return c.Fake.InvokesWatch(NewWatchAction("replicasets", c.Namespace, opts)) +} + +func (c *FakeReplicaSets) UpdateStatus(rs *extensions.ReplicaSet) (result *extensions.ReplicaSet, err error) { + obj, err := c.Fake.Invokes(NewUpdateSubresourceAction("replicasets", "status", c.Namespace, rs), rs) + if obj == nil { + return nil, err + } + + return obj.(*extensions.ReplicaSet), err +} diff --git a/ingress/vendor/k8s.io/kubernetes/pkg/client/unversioned/testclient/fake_replication_controllers.go b/ingress/vendor/k8s.io/kubernetes/pkg/client/unversioned/testclient/fake_replication_controllers.go new file mode 100644 index 0000000000..e44b826155 --- /dev/null +++ b/ingress/vendor/k8s.io/kubernetes/pkg/client/unversioned/testclient/fake_replication_controllers.go @@ -0,0 +1,82 @@ +/* +Copyright 2014 The Kubernetes Authors All rights reserved. + +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 testclient + +import ( + "k8s.io/kubernetes/pkg/api" + "k8s.io/kubernetes/pkg/watch" +) + +// FakeReplicationControllers implements ReplicationControllerInterface. Meant to be embedded into a struct to get a default +// implementation. This makes faking out just the method you want to test easier. +type FakeReplicationControllers struct { + Fake *Fake + Namespace string +} + +func (c *FakeReplicationControllers) Get(name string) (*api.ReplicationController, error) { + obj, err := c.Fake.Invokes(NewGetAction("replicationcontrollers", c.Namespace, name), &api.ReplicationController{}) + if obj == nil { + return nil, err + } + + return obj.(*api.ReplicationController), err +} + +func (c *FakeReplicationControllers) List(opts api.ListOptions) (*api.ReplicationControllerList, error) { + obj, err := c.Fake.Invokes(NewListAction("replicationcontrollers", c.Namespace, opts), &api.ReplicationControllerList{}) + if obj == nil { + return nil, err + } + + return obj.(*api.ReplicationControllerList), err +} + +func (c *FakeReplicationControllers) Create(controller *api.ReplicationController) (*api.ReplicationController, error) { + obj, err := c.Fake.Invokes(NewCreateAction("replicationcontrollers", c.Namespace, controller), controller) + if obj == nil { + return nil, err + } + + return obj.(*api.ReplicationController), err +} + +func (c *FakeReplicationControllers) Update(controller *api.ReplicationController) (*api.ReplicationController, error) { + obj, err := c.Fake.Invokes(NewUpdateAction("replicationcontrollers", c.Namespace, controller), controller) + if obj == nil { + return nil, err + } + + return obj.(*api.ReplicationController), err +} + +func (c *FakeReplicationControllers) UpdateStatus(controller *api.ReplicationController) (*api.ReplicationController, error) { + obj, err := c.Fake.Invokes(NewUpdateSubresourceAction("replicationcontrollers", "status", c.Namespace, controller), &api.ReplicationController{}) + if obj == nil { + return nil, err + } + return obj.(*api.ReplicationController), err +} + +func (c *FakeReplicationControllers) Delete(name string) error { + _, err := c.Fake.Invokes(NewDeleteAction("replicationcontrollers", c.Namespace, name), &api.ReplicationController{}) + return err +} + +func (c *FakeReplicationControllers) Watch(opts api.ListOptions) (watch.Interface, error) { + return c.Fake.InvokesWatch(NewWatchAction("replicationcontrollers", c.Namespace, opts)) +} diff --git a/ingress/vendor/k8s.io/kubernetes/pkg/client/unversioned/testclient/fake_resource_quotas.go b/ingress/vendor/k8s.io/kubernetes/pkg/client/unversioned/testclient/fake_resource_quotas.go new file mode 100644 index 0000000000..d5090f0d0f --- /dev/null +++ b/ingress/vendor/k8s.io/kubernetes/pkg/client/unversioned/testclient/fake_resource_quotas.go @@ -0,0 +1,83 @@ +/* +Copyright 2014 The Kubernetes Authors All rights reserved. + +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 testclient + +import ( + "k8s.io/kubernetes/pkg/api" + "k8s.io/kubernetes/pkg/watch" +) + +// FakeResourceQuotas implements ResourceQuotaInterface. Meant to be embedded into a struct to get a default +// implementation. This makes faking out just the methods you want to test easier. +type FakeResourceQuotas struct { + Fake *Fake + Namespace string +} + +func (c *FakeResourceQuotas) Get(name string) (*api.ResourceQuota, error) { + obj, err := c.Fake.Invokes(NewGetAction("resourcequotas", c.Namespace, name), &api.ResourceQuota{}) + if obj == nil { + return nil, err + } + + return obj.(*api.ResourceQuota), err +} + +func (c *FakeResourceQuotas) List(opts api.ListOptions) (*api.ResourceQuotaList, error) { + obj, err := c.Fake.Invokes(NewListAction("resourcequotas", c.Namespace, opts), &api.ResourceQuotaList{}) + if obj == nil { + return nil, err + } + + return obj.(*api.ResourceQuotaList), err +} + +func (c *FakeResourceQuotas) Create(resourceQuota *api.ResourceQuota) (*api.ResourceQuota, error) { + obj, err := c.Fake.Invokes(NewCreateAction("resourcequotas", c.Namespace, resourceQuota), resourceQuota) + if obj == nil { + return nil, err + } + + return obj.(*api.ResourceQuota), err +} + +func (c *FakeResourceQuotas) Update(resourceQuota *api.ResourceQuota) (*api.ResourceQuota, error) { + obj, err := c.Fake.Invokes(NewUpdateAction("resourcequotas", c.Namespace, resourceQuota), resourceQuota) + if obj == nil { + return nil, err + } + + return obj.(*api.ResourceQuota), err +} + +func (c *FakeResourceQuotas) Delete(name string) error { + _, err := c.Fake.Invokes(NewDeleteAction("resourcequotas", c.Namespace, name), &api.ResourceQuota{}) + return err +} + +func (c *FakeResourceQuotas) Watch(opts api.ListOptions) (watch.Interface, error) { + return c.Fake.InvokesWatch(NewWatchAction("resourcequotas", c.Namespace, opts)) +} + +func (c *FakeResourceQuotas) UpdateStatus(resourceQuota *api.ResourceQuota) (*api.ResourceQuota, error) { + obj, err := c.Fake.Invokes(NewUpdateSubresourceAction("resourcequotas", "status", c.Namespace, resourceQuota), resourceQuota) + if obj == nil { + return nil, err + } + + return obj.(*api.ResourceQuota), err +} diff --git a/ingress/vendor/k8s.io/kubernetes/pkg/client/unversioned/testclient/fake_scales.go b/ingress/vendor/k8s.io/kubernetes/pkg/client/unversioned/testclient/fake_scales.go new file mode 100644 index 0000000000..53ff5f87df --- /dev/null +++ b/ingress/vendor/k8s.io/kubernetes/pkg/client/unversioned/testclient/fake_scales.go @@ -0,0 +1,52 @@ +/* +Copyright 2015 The Kubernetes Authors All rights reserved. + +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 testclient + +import ( + "k8s.io/kubernetes/pkg/apis/extensions" +) + +// FakeScales implements ScaleInterface. Meant to be embedded into a struct to get a default +// implementation. This makes faking out just the methods you want to test easier. +type FakeScales struct { + Fake *FakeExperimental + Namespace string +} + +func (c *FakeScales) Get(kind string, name string) (result *extensions.Scale, err error) { + action := GetActionImpl{} + action.Verb = "get" + action.Namespace = c.Namespace + action.Resource = kind + action.Subresource = "scale" + action.Name = name + obj, err := c.Fake.Invokes(action, &extensions.Scale{}) + result = obj.(*extensions.Scale) + return +} + +func (c *FakeScales) Update(kind string, scale *extensions.Scale) (result *extensions.Scale, err error) { + action := UpdateActionImpl{} + action.Verb = "update" + action.Namespace = c.Namespace + action.Resource = kind + action.Subresource = "scale" + action.Object = scale + obj, err := c.Fake.Invokes(action, scale) + result = obj.(*extensions.Scale) + return +} diff --git a/ingress/vendor/k8s.io/kubernetes/pkg/client/unversioned/testclient/fake_secrets.go b/ingress/vendor/k8s.io/kubernetes/pkg/client/unversioned/testclient/fake_secrets.go new file mode 100644 index 0000000000..f54cffb871 --- /dev/null +++ b/ingress/vendor/k8s.io/kubernetes/pkg/client/unversioned/testclient/fake_secrets.go @@ -0,0 +1,74 @@ +/* +Copyright 2014 The Kubernetes Authors All rights reserved. + +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 testclient + +import ( + "k8s.io/kubernetes/pkg/api" + "k8s.io/kubernetes/pkg/watch" +) + +// Fake implements SecretInterface. Meant to be embedded into a struct to get a default +// implementation. This makes faking out just the method you want to test easier. +type FakeSecrets struct { + Fake *Fake + Namespace string +} + +func (c *FakeSecrets) Get(name string) (*api.Secret, error) { + obj, err := c.Fake.Invokes(NewGetAction("secrets", c.Namespace, name), &api.Secret{}) + if obj == nil { + return nil, err + } + + return obj.(*api.Secret), err +} + +func (c *FakeSecrets) List(opts api.ListOptions) (*api.SecretList, error) { + obj, err := c.Fake.Invokes(NewListAction("secrets", c.Namespace, opts), &api.SecretList{}) + if obj == nil { + return nil, err + } + + return obj.(*api.SecretList), err +} + +func (c *FakeSecrets) Create(secret *api.Secret) (*api.Secret, error) { + obj, err := c.Fake.Invokes(NewCreateAction("secrets", c.Namespace, secret), secret) + if obj == nil { + return nil, err + } + + return obj.(*api.Secret), err +} + +func (c *FakeSecrets) Update(secret *api.Secret) (*api.Secret, error) { + obj, err := c.Fake.Invokes(NewUpdateAction("secrets", c.Namespace, secret), secret) + if obj == nil { + return nil, err + } + + return obj.(*api.Secret), err +} + +func (c *FakeSecrets) Delete(name string) error { + _, err := c.Fake.Invokes(NewDeleteAction("secrets", c.Namespace, name), &api.Secret{}) + return err +} + +func (c *FakeSecrets) Watch(opts api.ListOptions) (watch.Interface, error) { + return c.Fake.InvokesWatch(NewWatchAction("secrets", c.Namespace, opts)) +} diff --git a/ingress/vendor/k8s.io/kubernetes/pkg/client/unversioned/testclient/fake_service_accounts.go b/ingress/vendor/k8s.io/kubernetes/pkg/client/unversioned/testclient/fake_service_accounts.go new file mode 100644 index 0000000000..e40641668e --- /dev/null +++ b/ingress/vendor/k8s.io/kubernetes/pkg/client/unversioned/testclient/fake_service_accounts.go @@ -0,0 +1,74 @@ +/* +Copyright 2014 The Kubernetes Authors All rights reserved. + +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 testclient + +import ( + "k8s.io/kubernetes/pkg/api" + "k8s.io/kubernetes/pkg/watch" +) + +// FakeServiceAccounts implements ServiceAccountsInterface. Meant to be embedded into a struct to get a default +// implementation. This makes faking out just the method you want to test easier. +type FakeServiceAccounts struct { + Fake *Fake + Namespace string +} + +func (c *FakeServiceAccounts) Get(name string) (*api.ServiceAccount, error) { + obj, err := c.Fake.Invokes(NewGetAction("serviceaccounts", c.Namespace, name), &api.ServiceAccount{}) + if obj == nil { + return nil, err + } + + return obj.(*api.ServiceAccount), err +} + +func (c *FakeServiceAccounts) List(opts api.ListOptions) (*api.ServiceAccountList, error) { + obj, err := c.Fake.Invokes(NewListAction("serviceaccounts", c.Namespace, opts), &api.ServiceAccountList{}) + if obj == nil { + return nil, err + } + + return obj.(*api.ServiceAccountList), err +} + +func (c *FakeServiceAccounts) Create(serviceAccount *api.ServiceAccount) (*api.ServiceAccount, error) { + obj, err := c.Fake.Invokes(NewCreateAction("serviceaccounts", c.Namespace, serviceAccount), serviceAccount) + if obj == nil { + return nil, err + } + + return obj.(*api.ServiceAccount), err +} + +func (c *FakeServiceAccounts) Update(serviceAccount *api.ServiceAccount) (*api.ServiceAccount, error) { + obj, err := c.Fake.Invokes(NewUpdateAction("serviceaccounts", c.Namespace, serviceAccount), serviceAccount) + if obj == nil { + return nil, err + } + + return obj.(*api.ServiceAccount), err +} + +func (c *FakeServiceAccounts) Delete(name string) error { + _, err := c.Fake.Invokes(NewDeleteAction("serviceaccounts", c.Namespace, name), &api.ServiceAccount{}) + return err +} + +func (c *FakeServiceAccounts) Watch(opts api.ListOptions) (watch.Interface, error) { + return c.Fake.InvokesWatch(NewWatchAction("serviceaccounts", c.Namespace, opts)) +} diff --git a/ingress/vendor/k8s.io/kubernetes/pkg/client/unversioned/testclient/fake_services.go b/ingress/vendor/k8s.io/kubernetes/pkg/client/unversioned/testclient/fake_services.go new file mode 100644 index 0000000000..fd4861ba14 --- /dev/null +++ b/ingress/vendor/k8s.io/kubernetes/pkg/client/unversioned/testclient/fake_services.go @@ -0,0 +1,88 @@ +/* +Copyright 2014 The Kubernetes Authors All rights reserved. + +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 testclient + +import ( + "k8s.io/kubernetes/pkg/api" + "k8s.io/kubernetes/pkg/client/restclient" + "k8s.io/kubernetes/pkg/watch" +) + +// Fake implements ServiceInterface. Meant to be embedded into a struct to get a default +// implementation. This makes faking out just the method you want to test easier. +type FakeServices struct { + Fake *Fake + Namespace string +} + +func (c *FakeServices) Get(name string) (*api.Service, error) { + obj, err := c.Fake.Invokes(NewGetAction("services", c.Namespace, name), &api.Service{}) + if obj == nil { + return nil, err + } + + return obj.(*api.Service), err +} + +func (c *FakeServices) List(opts api.ListOptions) (*api.ServiceList, error) { + obj, err := c.Fake.Invokes(NewListAction("services", c.Namespace, opts), &api.ServiceList{}) + if obj == nil { + return nil, err + } + + return obj.(*api.ServiceList), err +} + +func (c *FakeServices) Create(service *api.Service) (*api.Service, error) { + obj, err := c.Fake.Invokes(NewCreateAction("services", c.Namespace, service), service) + if obj == nil { + return nil, err + } + + return obj.(*api.Service), err +} + +func (c *FakeServices) Update(service *api.Service) (*api.Service, error) { + obj, err := c.Fake.Invokes(NewUpdateAction("services", c.Namespace, service), service) + if obj == nil { + return nil, err + } + + return obj.(*api.Service), err +} + +func (c *FakeServices) UpdateStatus(service *api.Service) (result *api.Service, err error) { + obj, err := c.Fake.Invokes(NewUpdateSubresourceAction("services", "status", c.Namespace, service), service) + if obj == nil { + return nil, err + } + + return obj.(*api.Service), err +} + +func (c *FakeServices) Delete(name string) error { + _, err := c.Fake.Invokes(NewDeleteAction("services", c.Namespace, name), &api.Service{}) + return err +} + +func (c *FakeServices) Watch(opts api.ListOptions) (watch.Interface, error) { + return c.Fake.InvokesWatch(NewWatchAction("services", c.Namespace, opts)) +} + +func (c *FakeServices) ProxyGet(scheme, name, port, path string, params map[string]string) restclient.ResponseWrapper { + return c.Fake.InvokesProxy(NewProxyGetAction("services", c.Namespace, scheme, name, port, path, params)) +} diff --git a/ingress/vendor/k8s.io/kubernetes/pkg/client/unversioned/testclient/fake_thirdpartyresources.go b/ingress/vendor/k8s.io/kubernetes/pkg/client/unversioned/testclient/fake_thirdpartyresources.go new file mode 100644 index 0000000000..cb4a15572a --- /dev/null +++ b/ingress/vendor/k8s.io/kubernetes/pkg/client/unversioned/testclient/fake_thirdpartyresources.go @@ -0,0 +1,82 @@ +/* +Copyright 2015 The Kubernetes Authors All rights reserved. + +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 testclient + +import ( + "k8s.io/kubernetes/pkg/api" + "k8s.io/kubernetes/pkg/apis/extensions" + kclientlib "k8s.io/kubernetes/pkg/client/unversioned" + "k8s.io/kubernetes/pkg/watch" +) + +// FakeThirdPartyResources implements ThirdPartyResourceInterface. Meant to be embedded into a struct to get a default +// implementation. This makes faking out just the method you want to test easier. +type FakeThirdPartyResources struct { + Fake *FakeExperimental +} + +// Ensure statically that FakeThirdPartyResources implements DaemonInterface. +var _ kclientlib.ThirdPartyResourceInterface = &FakeThirdPartyResources{} + +func (c *FakeThirdPartyResources) Get(name string) (*extensions.ThirdPartyResource, error) { + obj, err := c.Fake.Invokes(NewGetAction("thirdpartyresources", "", name), &extensions.ThirdPartyResource{}) + if obj == nil { + return nil, err + } + return obj.(*extensions.ThirdPartyResource), err +} + +func (c *FakeThirdPartyResources) List(opts api.ListOptions) (*extensions.ThirdPartyResourceList, error) { + obj, err := c.Fake.Invokes(NewListAction("thirdpartyresources", "", opts), &extensions.ThirdPartyResourceList{}) + if obj == nil { + return nil, err + } + return obj.(*extensions.ThirdPartyResourceList), err +} + +func (c *FakeThirdPartyResources) Create(daemon *extensions.ThirdPartyResource) (*extensions.ThirdPartyResource, error) { + obj, err := c.Fake.Invokes(NewCreateAction("thirdpartyresources", "", daemon), &extensions.ThirdPartyResource{}) + if obj == nil { + return nil, err + } + return obj.(*extensions.ThirdPartyResource), err +} + +func (c *FakeThirdPartyResources) Update(daemon *extensions.ThirdPartyResource) (*extensions.ThirdPartyResource, error) { + obj, err := c.Fake.Invokes(NewUpdateAction("thirdpartyresources", "", daemon), &extensions.ThirdPartyResource{}) + if obj == nil { + return nil, err + } + return obj.(*extensions.ThirdPartyResource), err +} + +func (c *FakeThirdPartyResources) UpdateStatus(daemon *extensions.ThirdPartyResource) (*extensions.ThirdPartyResource, error) { + obj, err := c.Fake.Invokes(NewUpdateSubresourceAction("thirdpartyresources", "status", "", daemon), &extensions.ThirdPartyResource{}) + if obj == nil { + return nil, err + } + return obj.(*extensions.ThirdPartyResource), err +} + +func (c *FakeThirdPartyResources) Delete(name string) error { + _, err := c.Fake.Invokes(NewDeleteAction("thirdpartyresources", "", name), &extensions.ThirdPartyResource{}) + return err +} + +func (c *FakeThirdPartyResources) Watch(opts api.ListOptions) (watch.Interface, error) { + return c.Fake.InvokesWatch(NewWatchAction("thirdpartyresources", "", opts)) +} diff --git a/ingress/vendor/k8s.io/kubernetes/pkg/client/unversioned/testclient/fixture.go b/ingress/vendor/k8s.io/kubernetes/pkg/client/unversioned/testclient/fixture.go new file mode 100644 index 0000000000..bb02e96d1d --- /dev/null +++ b/ingress/vendor/k8s.io/kubernetes/pkg/client/unversioned/testclient/fixture.go @@ -0,0 +1,313 @@ +/* +Copyright 2015 The Kubernetes Authors All rights reserved. + +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 testclient + +import ( + "fmt" + "io/ioutil" + "reflect" + "strings" + + "k8s.io/kubernetes/pkg/api/errors" + "k8s.io/kubernetes/pkg/api/meta" + "k8s.io/kubernetes/pkg/api/unversioned" + "k8s.io/kubernetes/pkg/client/restclient" + "k8s.io/kubernetes/pkg/runtime" + "k8s.io/kubernetes/pkg/util/yaml" + "k8s.io/kubernetes/pkg/watch" +) + +// ObjectRetriever abstracts the implementation for retrieving or setting generic +// objects. It is intended to be used to fake calls to a server by returning +// objects based on their kind and name. +type ObjectRetriever interface { + // Kind should return a resource or a list of resources (depending on the provided kind and + // name). It should return an error if the caller should communicate an error to the server. + Kind(gvk unversioned.GroupVersionKind, name string) (runtime.Object, error) + // Add adds a runtime object for test purposes into this object. + Add(runtime.Object) error +} + +// ObjectScheme abstracts the implementation of common operations on objects. +type ObjectScheme interface { + runtime.ObjectCreater + runtime.ObjectCopier + runtime.ObjectTyper +} + +// ObjectReaction returns a ReactionFunc that takes a generic action string of the form +// - or -- and attempts to return a runtime +// Object or error that matches the requested action. For instance, list-replicationControllers +// should attempt to return a list of replication controllers. This method delegates to the +// ObjectRetriever interface to satisfy retrieval of lists or retrieval of single items. +// TODO: add support for sub resources +func ObjectReaction(o ObjectRetriever, mapper meta.RESTMapper) ReactionFunc { + + return func(action Action) (bool, runtime.Object, error) { + kind, err := mapper.KindFor(unversioned.GroupVersionResource{Resource: action.GetResource()}) + if err != nil { + return false, nil, fmt.Errorf("unrecognized action %s: %v", action.GetResource(), err) + } + + // TODO: have mapper return a Kind for a subresource? + switch castAction := action.(type) { + case ListAction: + kind.Kind += "List" + resource, err := o.Kind(kind, "") + return true, resource, err + + case GetAction: + resource, err := o.Kind(kind, castAction.GetName()) + return true, resource, err + + case DeleteAction: + resource, err := o.Kind(kind, castAction.GetName()) + return true, resource, err + + case CreateAction: + accessor, err := meta.Accessor(castAction.GetObject()) + if err != nil { + return true, nil, err + } + resource, err := o.Kind(kind, accessor.GetName()) + return true, resource, err + + case UpdateAction: + accessor, err := meta.Accessor(castAction.GetObject()) + if err != nil { + return true, nil, err + } + resource, err := o.Kind(kind, accessor.GetName()) + return true, resource, err + + default: + return false, nil, fmt.Errorf("no reaction implemented for %s", action) + } + } +} + +// AddObjectsFromPath loads the JSON or YAML file containing Kubernetes API resources +// and adds them to the provided ObjectRetriever. +func AddObjectsFromPath(path string, o ObjectRetriever, decoder runtime.Decoder) error { + data, err := ioutil.ReadFile(path) + if err != nil { + return err + } + data, err = yaml.ToJSON(data) + if err != nil { + return err + } + obj, err := runtime.Decode(decoder, data) + if err != nil { + return err + } + if err := o.Add(obj); err != nil { + return err + } + return nil +} + +type objects struct { + types map[string][]runtime.Object + last map[string]int + scheme ObjectScheme + decoder runtime.Decoder +} + +var _ ObjectRetriever = &objects{} + +// NewObjects implements the ObjectRetriever interface by introspecting the +// objects provided to Add() and returning them when the Kind method is invoked. +// If an api.List object is provided to Add(), each child item is added. If an +// object is added that is itself a list (PodList, ServiceList) then that is added +// to the "PodList" kind. If no PodList is added, the retriever will take any loaded +// Pods and return them in a list. If an api.Status is added, and the Details.Kind field +// is set, that status will be returned instead (as an error if Status != Success, or +// as a runtime.Object if Status == Success). If multiple PodLists are provided, they +// will be returned in order by the Kind call, and the last PodList will be reused for +// subsequent calls. +func NewObjects(scheme ObjectScheme, decoder runtime.Decoder) ObjectRetriever { + return objects{ + types: make(map[string][]runtime.Object), + last: make(map[string]int), + scheme: scheme, + decoder: decoder, + } +} + +func (o objects) Kind(kind unversioned.GroupVersionKind, name string) (runtime.Object, error) { + kind.Version = runtime.APIVersionInternal + + empty, _ := o.scheme.New(kind) + nilValue := reflect.Zero(reflect.TypeOf(empty)).Interface().(runtime.Object) + + arr, ok := o.types[kind.Kind] + if !ok { + if strings.HasSuffix(kind.Kind, "List") { + itemKind := kind.Kind[:len(kind.Kind)-4] + arr, ok := o.types[itemKind] + if !ok { + return empty, nil + } + out, err := o.scheme.New(kind) + if err != nil { + return nilValue, err + } + if err := meta.SetList(out, arr); err != nil { + return nilValue, err + } + if out, err = o.scheme.Copy(out); err != nil { + return nilValue, err + } + return out, nil + } + return nilValue, errors.NewNotFound(unversioned.GroupResource{Group: kind.Group, Resource: kind.Kind}, name) + } + + index := o.last[kind.Kind] + if index >= len(arr) { + index = len(arr) - 1 + } + if index < 0 { + return nilValue, errors.NewNotFound(unversioned.GroupResource{Group: kind.Group, Resource: kind.Kind}, name) + } + out, err := o.scheme.Copy(arr[index]) + if err != nil { + return nilValue, err + } + o.last[kind.Kind] = index + 1 + + if status, ok := out.(*unversioned.Status); ok { + if status.Details != nil { + status.Details.Kind = kind.Kind + } + if status.Status != unversioned.StatusSuccess { + return nilValue, &errors.StatusError{ErrStatus: *status} + } + } + + return out, nil +} + +func (o objects) Add(obj runtime.Object) error { + gvk, err := o.scheme.ObjectKind(obj) + if err != nil { + return err + } + kind := gvk.Kind + + switch { + case meta.IsListType(obj): + if kind != "List" { + o.types[kind] = append(o.types[kind], obj) + } + + list, err := meta.ExtractList(obj) + if err != nil { + return err + } + if errs := runtime.DecodeList(list, o.decoder); len(errs) > 0 { + return errs[0] + } + for _, obj := range list { + if err := o.Add(obj); err != nil { + return err + } + } + default: + if status, ok := obj.(*unversioned.Status); ok && status.Details != nil { + kind = status.Details.Kind + } + o.types[kind] = append(o.types[kind], obj) + } + + return nil +} + +func DefaultWatchReactor(watchInterface watch.Interface, err error) WatchReactionFunc { + return func(action Action) (bool, watch.Interface, error) { + return true, watchInterface, err + } +} + +// SimpleReactor is a Reactor. Each reaction function is attached to a given verb,resource tuple. "*" in either field matches everything for that value. +// For instance, *,pods matches all verbs on pods. This allows for easier composition of reaction functions +type SimpleReactor struct { + Verb string + Resource string + + Reaction ReactionFunc +} + +func (r *SimpleReactor) Handles(action Action) bool { + verbCovers := r.Verb == "*" || r.Verb == action.GetVerb() + if !verbCovers { + return false + } + resourceCovers := r.Resource == "*" || r.Resource == action.GetResource() + if !resourceCovers { + return false + } + + return true +} + +func (r *SimpleReactor) React(action Action) (bool, runtime.Object, error) { + return r.Reaction(action) +} + +// SimpleWatchReactor is a WatchReactor. Each reaction function is attached to a given resource. "*" matches everything for that value. +// For instance, *,pods matches all verbs on pods. This allows for easier composition of reaction functions +type SimpleWatchReactor struct { + Resource string + + Reaction WatchReactionFunc +} + +func (r *SimpleWatchReactor) Handles(action Action) bool { + resourceCovers := r.Resource == "*" || r.Resource == action.GetResource() + if !resourceCovers { + return false + } + + return true +} + +func (r *SimpleWatchReactor) React(action Action) (bool, watch.Interface, error) { + return r.Reaction(action) +} + +// SimpleProxyReactor is a ProxyReactor. Each reaction function is attached to a given resource. "*" matches everything for that value. +// For instance, *,pods matches all verbs on pods. This allows for easier composition of reaction functions. +type SimpleProxyReactor struct { + Resource string + + Reaction ProxyReactionFunc +} + +func (r *SimpleProxyReactor) Handles(action Action) bool { + resourceCovers := r.Resource == "*" || r.Resource == action.GetResource() + if !resourceCovers { + return false + } + + return true +} + +func (r *SimpleProxyReactor) React(action Action) (bool, restclient.ResponseWrapper, error) { + return r.Reaction(action) +} diff --git a/ingress/vendor/k8s.io/kubernetes/pkg/client/unversioned/testclient/testclient.go b/ingress/vendor/k8s.io/kubernetes/pkg/client/unversioned/testclient/testclient.go new file mode 100644 index 0000000000..258a0f5afb --- /dev/null +++ b/ingress/vendor/k8s.io/kubernetes/pkg/client/unversioned/testclient/testclient.go @@ -0,0 +1,419 @@ +/* +Copyright 2015 The Kubernetes Authors All rights reserved. + +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 testclient + +import ( + "fmt" + "sync" + + "github.com/emicklei/go-restful/swagger" + + "k8s.io/kubernetes/pkg/api" + "k8s.io/kubernetes/pkg/api/unversioned" + "k8s.io/kubernetes/pkg/api/v1" + "k8s.io/kubernetes/pkg/apimachinery/registered" + "k8s.io/kubernetes/pkg/client/restclient" + "k8s.io/kubernetes/pkg/client/typed/discovery" + client "k8s.io/kubernetes/pkg/client/unversioned" + "k8s.io/kubernetes/pkg/runtime" + "k8s.io/kubernetes/pkg/version" + "k8s.io/kubernetes/pkg/watch" +) + +// NewSimpleFake returns a client that will respond with the provided objects +func NewSimpleFake(objects ...runtime.Object) *Fake { + o := NewObjects(api.Scheme, api.Codecs.UniversalDecoder()) + for _, obj := range objects { + if err := o.Add(obj); err != nil { + panic(err) + } + } + + fakeClient := &Fake{} + fakeClient.AddReactor("*", "*", ObjectReaction(o, registered.RESTMapper())) + + fakeClient.AddWatchReactor("*", DefaultWatchReactor(watch.NewFake(), nil)) + + return fakeClient +} + +// Fake implements client.Interface. Meant to be embedded into a struct to get a default +// implementation. This makes faking out just the method you want to test easier. +type Fake struct { + sync.RWMutex + actions []Action // these may be castable to other types, but "Action" is the minimum + + // ReactionChain is the list of reactors that will be attempted for every request in the order they are tried + ReactionChain []Reactor + // WatchReactionChain is the list of watch reactors that will be attempted for every request in the order they are tried + WatchReactionChain []WatchReactor + // ProxyReactionChain is the list of proxy reactors that will be attempted for every request in the order they are tried + ProxyReactionChain []ProxyReactor + + Resources map[string]*unversioned.APIResourceList +} + +// Reactor is an interface to allow the composition of reaction functions. +type Reactor interface { + // Handles indicates whether or not this Reactor deals with a given action + Handles(action Action) bool + // React handles the action and returns results. It may choose to delegate by indicated handled=false + React(action Action) (handled bool, ret runtime.Object, err error) +} + +// WatchReactor is an interface to allow the composition of watch functions. +type WatchReactor interface { + // Handles indicates whether or not this Reactor deals with a given action + Handles(action Action) bool + // React handles a watch action and returns results. It may choose to delegate by indicated handled=false + React(action Action) (handled bool, ret watch.Interface, err error) +} + +// ProxyReactor is an interface to allow the composition of proxy get functions. +type ProxyReactor interface { + // Handles indicates whether or not this Reactor deals with a given action + Handles(action Action) bool + // React handles a watch action and returns results. It may choose to delegate by indicated handled=false + React(action Action) (handled bool, ret restclient.ResponseWrapper, err error) +} + +// ReactionFunc is a function that returns an object or error for a given Action. If "handled" is false, +// then the test client will continue ignore the results and continue to the next ReactionFunc +type ReactionFunc func(action Action) (handled bool, ret runtime.Object, err error) + +// WatchReactionFunc is a function that returns a watch interface. If "handled" is false, +// then the test client will continue ignore the results and continue to the next ReactionFunc +type WatchReactionFunc func(action Action) (handled bool, ret watch.Interface, err error) + +// ProxyReactionFunc is a function that returns a ResponseWrapper interface for a given Action. If "handled" is false, +// then the test client will continue ignore the results and continue to the next ProxyReactionFunc +type ProxyReactionFunc func(action Action) (handled bool, ret restclient.ResponseWrapper, err error) + +// AddReactor appends a reactor to the end of the chain +func (c *Fake) AddReactor(verb, resource string, reaction ReactionFunc) { + c.ReactionChain = append(c.ReactionChain, &SimpleReactor{verb, resource, reaction}) +} + +// PrependReactor adds a reactor to the beginning of the chain +func (c *Fake) PrependReactor(verb, resource string, reaction ReactionFunc) { + c.ReactionChain = append([]Reactor{&SimpleReactor{verb, resource, reaction}}, c.ReactionChain...) +} + +// AddWatchReactor appends a reactor to the end of the chain +func (c *Fake) AddWatchReactor(resource string, reaction WatchReactionFunc) { + c.WatchReactionChain = append(c.WatchReactionChain, &SimpleWatchReactor{resource, reaction}) +} + +// PrependWatchReactor adds a reactor to the beginning of the chain +func (c *Fake) PrependWatchReactor(resource string, reaction WatchReactionFunc) { + c.WatchReactionChain = append([]WatchReactor{&SimpleWatchReactor{resource, reaction}}, c.WatchReactionChain...) +} + +// AddProxyReactor appends a reactor to the end of the chain +func (c *Fake) AddProxyReactor(resource string, reaction ProxyReactionFunc) { + c.ProxyReactionChain = append(c.ProxyReactionChain, &SimpleProxyReactor{resource, reaction}) +} + +// PrependProxyReactor adds a reactor to the beginning of the chain +func (c *Fake) PrependProxyReactor(resource string, reaction ProxyReactionFunc) { + c.ProxyReactionChain = append([]ProxyReactor{&SimpleProxyReactor{resource, reaction}}, c.ProxyReactionChain...) +} + +// Invokes records the provided Action and then invokes the ReactFn (if provided). +// defaultReturnObj is expected to be of the same type a normal call would return. +func (c *Fake) Invokes(action Action, defaultReturnObj runtime.Object) (runtime.Object, error) { + c.Lock() + defer c.Unlock() + + c.actions = append(c.actions, action) + for _, reactor := range c.ReactionChain { + if !reactor.Handles(action) { + continue + } + + handled, ret, err := reactor.React(action) + if !handled { + continue + } + + return ret, err + } + + return defaultReturnObj, nil +} + +// InvokesWatch records the provided Action and then invokes the ReactFn (if provided). +func (c *Fake) InvokesWatch(action Action) (watch.Interface, error) { + c.Lock() + defer c.Unlock() + + c.actions = append(c.actions, action) + for _, reactor := range c.WatchReactionChain { + if !reactor.Handles(action) { + continue + } + + handled, ret, err := reactor.React(action) + if !handled { + continue + } + + return ret, err + } + + return nil, fmt.Errorf("unhandled watch: %#v", action) +} + +// InvokesProxy records the provided Action and then invokes the ReactFn (if provided). +func (c *Fake) InvokesProxy(action Action) restclient.ResponseWrapper { + c.Lock() + defer c.Unlock() + + c.actions = append(c.actions, action) + for _, reactor := range c.ProxyReactionChain { + if !reactor.Handles(action) { + continue + } + + handled, ret, err := reactor.React(action) + if !handled || err != nil { + continue + } + + return ret + } + + return nil +} + +// ClearActions clears the history of actions called on the fake client +func (c *Fake) ClearActions() { + c.Lock() + c.Unlock() + + c.actions = make([]Action, 0) +} + +// Actions returns a chronologically ordered slice fake actions called on the fake client +func (c *Fake) Actions() []Action { + c.RLock() + defer c.RUnlock() + fa := make([]Action, len(c.actions)) + copy(fa, c.actions) + return fa +} + +func (c *Fake) LimitRanges(namespace string) client.LimitRangeInterface { + return &FakeLimitRanges{Fake: c, Namespace: namespace} +} + +func (c *Fake) ResourceQuotas(namespace string) client.ResourceQuotaInterface { + return &FakeResourceQuotas{Fake: c, Namespace: namespace} +} + +func (c *Fake) ReplicationControllers(namespace string) client.ReplicationControllerInterface { + return &FakeReplicationControllers{Fake: c, Namespace: namespace} +} + +func (c *Fake) Nodes() client.NodeInterface { + return &FakeNodes{Fake: c} +} + +func (c *Fake) PodSecurityPolicies() client.PodSecurityPolicyInterface { + return &FakePodSecurityPolicy{Fake: c} +} + +func (c *Fake) Events(namespace string) client.EventInterface { + return &FakeEvents{Fake: c, Namespace: namespace} +} + +func (c *Fake) Endpoints(namespace string) client.EndpointsInterface { + return &FakeEndpoints{Fake: c, Namespace: namespace} +} + +func (c *Fake) PersistentVolumes() client.PersistentVolumeInterface { + return &FakePersistentVolumes{Fake: c} +} + +func (c *Fake) PersistentVolumeClaims(namespace string) client.PersistentVolumeClaimInterface { + return &FakePersistentVolumeClaims{Fake: c, Namespace: namespace} +} + +func (c *Fake) Pods(namespace string) client.PodInterface { + return &FakePods{Fake: c, Namespace: namespace} +} + +func (c *Fake) PodTemplates(namespace string) client.PodTemplateInterface { + return &FakePodTemplates{Fake: c, Namespace: namespace} +} + +func (c *Fake) Services(namespace string) client.ServiceInterface { + return &FakeServices{Fake: c, Namespace: namespace} +} + +func (c *Fake) ServiceAccounts(namespace string) client.ServiceAccountsInterface { + return &FakeServiceAccounts{Fake: c, Namespace: namespace} +} + +func (c *Fake) Secrets(namespace string) client.SecretsInterface { + return &FakeSecrets{Fake: c, Namespace: namespace} +} + +func (c *Fake) Namespaces() client.NamespaceInterface { + return &FakeNamespaces{Fake: c} +} + +func (c *Fake) Autoscaling() client.AutoscalingInterface { + return &FakeAutoscaling{c} +} + +func (c *Fake) Batch() client.BatchInterface { + return &FakeBatch{c} +} + +func (c *Fake) Extensions() client.ExtensionsInterface { + return &FakeExperimental{c} +} + +func (c *Fake) Discovery() discovery.DiscoveryInterface { + return &FakeDiscovery{c} +} + +func (c *Fake) ComponentStatuses() client.ComponentStatusInterface { + return &FakeComponentStatuses{Fake: c} +} + +func (c *Fake) ConfigMaps(namespace string) client.ConfigMapsInterface { + return &FakeConfigMaps{Fake: c, Namespace: namespace} +} + +// SwaggerSchema returns an empty swagger.ApiDeclaration for testing +func (c *Fake) SwaggerSchema(version unversioned.GroupVersion) (*swagger.ApiDeclaration, error) { + action := ActionImpl{} + action.Verb = "get" + if version == v1.SchemeGroupVersion { + action.Resource = "/swaggerapi/api/" + version.Version + } else { + action.Resource = "/swaggerapi/apis/" + version.Group + "/" + version.Version + } + + c.Invokes(action, nil) + return &swagger.ApiDeclaration{}, nil +} + +// NewSimpleFakeAutoscaling returns a client that will respond with the provided objects +func NewSimpleFakeAutoscaling(objects ...runtime.Object) *FakeAutoscaling { + return &FakeAutoscaling{Fake: NewSimpleFake(objects...)} +} + +type FakeAutoscaling struct { + *Fake +} + +func (c *FakeAutoscaling) HorizontalPodAutoscalers(namespace string) client.HorizontalPodAutoscalerInterface { + return &FakeHorizontalPodAutoscalersV1{Fake: c, Namespace: namespace} +} + +// NewSimpleFakeBatch returns a client that will respond with the provided objects +func NewSimpleFakeBatch(objects ...runtime.Object) *FakeBatch { + return &FakeBatch{Fake: NewSimpleFake(objects...)} +} + +type FakeBatch struct { + *Fake +} + +func (c *FakeBatch) Jobs(namespace string) client.JobInterface { + return &FakeJobsV1{Fake: c, Namespace: namespace} +} + +// NewSimpleFakeExp returns a client that will respond with the provided objects +func NewSimpleFakeExp(objects ...runtime.Object) *FakeExperimental { + return &FakeExperimental{Fake: NewSimpleFake(objects...)} +} + +type FakeExperimental struct { + *Fake +} + +func (c *FakeExperimental) DaemonSets(namespace string) client.DaemonSetInterface { + return &FakeDaemonSets{Fake: c, Namespace: namespace} +} + +func (c *FakeExperimental) HorizontalPodAutoscalers(namespace string) client.HorizontalPodAutoscalerInterface { + return &FakeHorizontalPodAutoscalers{Fake: c, Namespace: namespace} +} + +func (c *FakeExperimental) Deployments(namespace string) client.DeploymentInterface { + return &FakeDeployments{Fake: c, Namespace: namespace} +} + +func (c *FakeExperimental) Scales(namespace string) client.ScaleInterface { + return &FakeScales{Fake: c, Namespace: namespace} +} + +func (c *FakeExperimental) Jobs(namespace string) client.JobInterface { + return &FakeJobs{Fake: c, Namespace: namespace} +} + +func (c *FakeExperimental) Ingress(namespace string) client.IngressInterface { + return &FakeIngress{Fake: c, Namespace: namespace} +} + +func (c *FakeExperimental) ThirdPartyResources() client.ThirdPartyResourceInterface { + return &FakeThirdPartyResources{Fake: c} +} + +func (c *FakeExperimental) ReplicaSets(namespace string) client.ReplicaSetInterface { + return &FakeReplicaSets{Fake: c, Namespace: namespace} +} + +type FakeDiscovery struct { + *Fake +} + +func (c *FakeDiscovery) ServerResourcesForGroupVersion(groupVersion string) (*unversioned.APIResourceList, error) { + action := ActionImpl{ + Verb: "get", + Resource: "resource", + } + c.Invokes(action, nil) + return c.Resources[groupVersion], nil +} + +func (c *FakeDiscovery) ServerResources() (map[string]*unversioned.APIResourceList, error) { + action := ActionImpl{ + Verb: "get", + Resource: "resource", + } + c.Invokes(action, nil) + return c.Resources, nil +} + +func (c *FakeDiscovery) ServerGroups() (*unversioned.APIGroupList, error) { + return nil, nil +} + +func (c *FakeDiscovery) ServerVersion() (*version.Info, error) { + action := ActionImpl{} + action.Verb = "get" + action.Resource = "version" + + c.Invokes(action, nil) + versionInfo := version.Get() + return &versionInfo, nil +} From 271e501edc32d58fb44bcbb773b6f6136d780240 Mon Sep 17 00:00:00 2001 From: Manuel de Brito Fontes Date: Wed, 11 May 2016 02:22:17 -0300 Subject: [PATCH 3/4] Use authentication and add example --- ingress/controllers/nginx/README.md | 23 ++++ ingress/controllers/nginx/auth/main.go | 90 +++++++++---- ingress/controllers/nginx/auth/main_test.go | 81 +++++++++-- .../controllers/nginx/examples/auth/README.md | 126 ++++++++++++++++++ .../nginx/examples/auth/auth-ingress.yaml | 18 --- 5 files changed, 283 insertions(+), 55 deletions(-) create mode 100644 ingress/controllers/nginx/examples/auth/README.md delete mode 100644 ingress/controllers/nginx/examples/auth/auth-ingress.yaml diff --git a/ingress/controllers/nginx/README.md b/ingress/controllers/nginx/README.md index fa0d892370..ae62c3a2ed 100644 --- a/ingress/controllers/nginx/README.md +++ b/ingress/controllers/nginx/README.md @@ -213,6 +213,29 @@ This means only one of the rules should define annotations to configure the upst Please check the [auth](examples/custom-upstream-check/README.md) example + ### Authentication + + Is possible to add authentication adding additional annotations in the Ingress rule. The source of the authentication is a secret that contains usernames and passwords inside the the key `auth` + + The annotations are: + + ``` + ingress-nginx.kubernetes.io/auth-type:[basic|digest] + ``` + + Indicates the [HTTP Authentication Type: Basic or Digest Access Authentication](https://tools.ietf.org/html/rfc2617). + + ``` + ingress-nginx.kubernetes.io/auth-secret:secretName + ``` + + Name of the secret that contains the usernames and passwords with access to the `path/s` defined in the Ingress Rule. + The secret must be created in the same namespace than the Ingress rule + + ``` + ingress-nginx.kubernetes.io/auth-realm:"realm string" + ``` + ### NGINX status page diff --git a/ingress/controllers/nginx/auth/main.go b/ingress/controllers/nginx/auth/main.go index 4d74267d81..5169a74c7c 100644 --- a/ingress/controllers/nginx/auth/main.go +++ b/ingress/controllers/nginx/auth/main.go @@ -17,10 +17,13 @@ limitations under the License. package auth import ( - "bytes" "errors" "fmt" "io/ioutil" + "os" + "regexp" + + "github.com/golang/glog" "k8s.io/kubernetes/pkg/api" "k8s.io/kubernetes/pkg/apis/extensions" @@ -33,11 +36,19 @@ const ( authRealm = "ingress-nginx.kubernetes.io/auth-realm" defAuthRealm = "Authentication Required" + + // DefAuthDirectory default directory used to store files + // to authenticate request in NGINX + DefAuthDirectory = "/etc/nginx/auth" ) +func init() { + // TODO: check permissions required + os.MkdirAll(DefAuthDirectory, 0655) +} + var ( - authTypeRegex = "basic|digest" - authDir = "/etc/nginx/auth" + authTypeRegex = regexp.MustCompile(`basic|digest`) // ErrInvalidAuthType is return in case of unsupported authentication type ErrInvalidAuthType = errors.New("invalid authentication type") @@ -47,14 +58,27 @@ var ( // ErrMissingSecretName is returned when the name of the secret is missing ErrMissingSecretName = errors.New("secret name is missing") + + // ErrMissingAuthInSecret is returned when there is no auth key in secret data + ErrMissingAuthInSecret = errors.New("the secret does not contains the auth key") ) +// ErrMissingAnnotations is returned when the ingress rule +// does not contains annotations related with authentication +type ErrMissingAnnotations struct { + msg string +} + +func (e ErrMissingAnnotations) Error() string { + return e.msg +} + // Nginx returns authentication configuration for an Ingress rule type Nginx struct { - Type string - Secret *api.Secret - Realm string - File string + Type string + Realm string + File string + Secured bool } type ingAnnotations map[string]string @@ -65,7 +89,8 @@ func (a ingAnnotations) authType() (string, error) { return "", ErrMissingAuthType } - if val != "basic" || val != "digest" { + if !authTypeRegex.MatchString(val) { + glog.Warningf("%v is not a valid authentication type", val) return "", ErrInvalidAuthType } @@ -90,52 +115,59 @@ func (a ingAnnotations) secretName() (string, error) { return val, nil } -// Parse parses the annotations contained in the ingress rule -// used to add authentication in the paths defined in the rule +// ParseAnnotations parses the annotations contained in the ingress +// rule used to add authentication in the paths defined in the rule // and generated an htpasswd compatible file to be used as source // during the authentication process -func Parse(kubeClient client.Interface, ing *extensions.Ingress) (*Nginx, error) { +func ParseAnnotations(kubeClient client.Interface, ing *extensions.Ingress, authDir string) (*Nginx, error) { + if ing.GetAnnotations() == nil { + return &Nginx{}, ErrMissingAnnotations{"missing authentication annotations"} + } + at, err := ingAnnotations(ing.GetAnnotations()).authType() if err != nil { - return nil, err + return &Nginx{}, err } s, err := ingAnnotations(ing.GetAnnotations()).secretName() if err != nil { - return nil, err + return &Nginx{}, err } secret, err := kubeClient.Secrets(ing.Namespace).Get(s) if err != nil { - return nil, err + return &Nginx{}, err } realm := ingAnnotations(ing.GetAnnotations()).realm() passFile := fmt.Sprintf("%v/%v-%v.passwd", authDir, ing.GetNamespace(), ing.GetName()) - err = dumpSecret(passFile, at, secret) + err = dumpSecret(passFile, secret) if err != nil { - return nil, err - } - - n := &Nginx{ - Type: at, - Secret: secret, - Realm: realm, - File: passFile, + return &Nginx{}, err } - return n, nil + return &Nginx{ + Type: at, + Realm: realm, + File: passFile, + Secured: true, + }, nil } // dumpSecret dumps the content of a secret into a file // in the expected format for the specified authorization -func dumpSecret(filename, auth string, secret *api.Secret) error { - buf := bytes.NewBuffer([]byte{}) +func dumpSecret(filename string, secret *api.Secret) error { + val, ok := secret.Data["auth"] + if !ok { + return ErrMissingAuthInSecret + } - for key, value := range secret.Data { - fmt.Fprintf(buf, "%v:%s\n", key, value) + // TODO: check permissions required + err := ioutil.WriteFile(filename, val, 0777) + if err != nil { + return err } - return ioutil.WriteFile(filename, buf.Bytes(), 600) + return nil } diff --git a/ingress/controllers/nginx/auth/main_test.go b/ingress/controllers/nginx/auth/main_test.go index 2a11dd4946..eed975e949 100644 --- a/ingress/controllers/nginx/auth/main_test.go +++ b/ingress/controllers/nginx/auth/main_test.go @@ -17,7 +17,11 @@ limitations under the License. package auth import ( + "fmt" + "io/ioutil" + "os" "testing" + "time" "k8s.io/kubernetes/pkg/api" "k8s.io/kubernetes/pkg/apis/extensions" @@ -65,15 +69,20 @@ type secretsClient struct { unversioned.Interface } -func mockClient() *testclient.Fake { - secretObj := &api.Secret{ +// dummySecret generates a secret with one user inside the auth key +// foo:md5(bar) +func dummySecret() *api.Secret { + return &api.Secret{ ObjectMeta: api.ObjectMeta{ Namespace: api.NamespaceDefault, Name: "demo-secret", }, + Data: map[string][]byte{"auth": []byte("foo:$apr1$OFG3Xybp$ckL0FHDAkoXYIlH9.cysT0")}, } +} - return testclient.NewSimpleFake(secretObj) +func mockClient() *testclient.Fake { + return testclient.NewSimpleFake(dummySecret()) } func TestAnnotations(t *testing.T) { @@ -121,21 +130,77 @@ func TestAnnotations(t *testing.T) { func TestIngressWithoutAuth(t *testing.T) { ing := buildIngress() client := mockClient() - _, err := Parse(client, ing) + _, err := ParseAnnotations(client, ing, "") if err == nil { t.Error("Expected error with ingress without annotations") } - if err != ErrMissingAuthType { + if err == ErrMissingAuthType { t.Errorf("Expected MissingAuthType error but returned %v", err) } } -func TestIngressBasicAuth(t *testing.T) { +func TestIngressAuth(t *testing.T) { + ing := buildIngress() + + data := map[string]string{} + data[authType] = "basic" + data[authSecret] = "demo-secret" + data[authRealm] = "-realm-" + ing.SetAnnotations(data) + + _, dir, _ := dummySecretContent(t) + defer os.RemoveAll(dir) + + client := mockClient() + nginxAuth, err := ParseAnnotations(client, ing, dir) + if err != nil { + t.Errorf("Uxpected error with ingress: %v", err) + } + + if nginxAuth.Type != "basic" { + t.Errorf("Expected basic as auth type but returned %s", nginxAuth.Type) + } + if nginxAuth.Realm != "-realm-" { + t.Errorf("Expected -realm- as realm but returned %s", nginxAuth.Realm) + } + if nginxAuth.Secured != true { + t.Errorf("Expected true as secured but returned %v", nginxAuth.Secured) + } } -func TestIngressDigestAuth(t *testing.T) { +func dummySecretContent(t *testing.T) (string, string, *api.Secret) { + dir, err := ioutil.TempDir("", fmt.Sprintf("%v", time.Now().Unix())) + if err != nil { + t.Error(err) + } + + tmpfile, err := ioutil.TempFile("", "example-") + if err != nil { + t.Error(err) + } + defer tmpfile.Close() + + s := dummySecret() + + return tmpfile.Name(), dir, s } -func TestIngressMissingAnnotation(t *testing.T) { +func TestDumpSecret(t *testing.T) { + tmpfile, dir, s := dummySecretContent(t) + defer os.RemoveAll(dir) + + sd := s.Data + s.Data = nil + + err := dumpSecret(tmpfile, s) + if err == nil { + t.Errorf("Expected error with secret without auth") + } + + s.Data = sd + err = dumpSecret(tmpfile, s) + if err != nil { + t.Errorf("Unexpected error creating htpasswd file %v: %v", tmpfile, err) + } } diff --git a/ingress/controllers/nginx/examples/auth/README.md b/ingress/controllers/nginx/examples/auth/README.md new file mode 100644 index 0000000000..ba0f0c8662 --- /dev/null +++ b/ingress/controllers/nginx/examples/auth/README.md @@ -0,0 +1,126 @@ + +This example shows how to add authentication in a Ingress rule using a secret that contains a file generated with `htpasswd`. + + +``` +$ htpasswd -c auth foo +New password: +New password: +Re-type new password: +Adding password for user foo +``` + +``` +$ kubectl create secret generic basic-auth --from-file=auth +secret "basic-auth" created +``` + +``` +$ kubectl get secret basic-auth -o yaml +apiVersion: v1 +data: + auth: Zm9vOiRhcHIxJE9GRzNYeWJwJGNrTDBGSERBa29YWUlsSDkuY3lzVDAK +kind: Secret +metadata: + name: basic-auth + namespace: default +type: Opaque +``` + +``` +echo " +apiVersion: extensions/v1beta1 +kind: Ingress +metadata: + name: ingress-with-auth + annotations: + # type of authentication + ingress-nginx.kubernetes.io/auth-type: basic + # name of the secret that contains the user/password definitions + ingress-nginx.kubernetes.io/auth-secret: basic-auth + # message to display with an appropiate context why the authentication is required + ingress-nginx.kubernetes.io/auth-realm: "Authentication Required - foo" +spec: + rules: + - host: foo.bar.com + http: + paths: + - path: / + backend: + serviceName: echoheaders + servicePort: 80 +" | kubectl create -f - +``` + +``` +$ curl -v http://10.2.29.4/ -H 'Host: foo.bar.com' +* Trying 10.2.29.4... +* Connected to 10.2.29.4 (10.2.29.4) port 80 (#0) +> GET / HTTP/1.1 +> Host: foo.bar.com +> User-Agent: curl/7.43.0 +> Accept: */* +> +< HTTP/1.1 401 Unauthorized +< Server: nginx/1.10.0 +< Date: Wed, 11 May 2016 05:27:23 GMT +< Content-Type: text/html +< Content-Length: 195 +< Connection: keep-alive +< WWW-Authenticate: Basic realm="Authentication Required - foo" +< + +401 Authorization Required + +

401 Authorization Required

+
nginx/1.10.0
+ + +* Connection #0 to host 10.2.29.4 left intact +``` + +``` +$ curl -v http://10.2.29.4/ -H 'Host: foo.bar.com' -u 'foo:bar' +* Trying 10.2.29.4... +* Connected to 10.2.29.4 (10.2.29.4) port 80 (#0) +* Server auth using Basic with user 'foo' +> GET / HTTP/1.1 +> Host: foo.bar.com +> Authorization: Basic Zm9vOmJhcg== +> User-Agent: curl/7.43.0 +> Accept: */* +> +< HTTP/1.1 200 OK +< Server: nginx/1.10.0 +< Date: Wed, 11 May 2016 06:05:26 GMT +< Content-Type: text/plain +< Transfer-Encoding: chunked +< Connection: keep-alive +< Vary: Accept-Encoding +< +CLIENT VALUES: +client_address=10.2.29.4 +command=GET +real path=/ +query=nil +request_version=1.1 +request_uri=http://foo.bar.com:8080/ + +SERVER VALUES: +server_version=nginx: 1.9.11 - lua: 10001 + +HEADERS RECEIVED: +accept=*/* +authorization=Basic Zm9vOmJhcg== +connection=close +host=foo.bar.com +user-agent=curl/7.43.0 +x-forwarded-for=10.2.29.1 +x-forwarded-host=foo.bar.com +x-forwarded-port=80 +x-forwarded-proto=http +x-real-ip=10.2.29.1 +BODY: +* Connection #0 to host 10.2.29.4 left intact +-no body in request- +``` diff --git a/ingress/controllers/nginx/examples/auth/auth-ingress.yaml b/ingress/controllers/nginx/examples/auth/auth-ingress.yaml deleted file mode 100644 index 0942cbb699..0000000000 --- a/ingress/controllers/nginx/examples/auth/auth-ingress.yaml +++ /dev/null @@ -1,18 +0,0 @@ -# An Ingress with 2 hosts and 3 endpoints -apiVersion: extensions/v1beta1 -kind: Ingress -metadata: - name: echo-with-auth -annotations: - ingress-nginx.kubernetes.io/auth-type: basic - ingress-nginx.kubernetes.io/auth-secret: echo-auth-secret - ingress-nginx.kubernetes.io/auth-realm: "Ingress with Basic Authentication" -spec: - rules: - - host: foo.bar.com - http: - paths: - - path: / - backend: - serviceName: echoheaders-x - servicePort: 80 From 4cda656996aed4d52aa5ba4c5135dcedbba9505c Mon Sep 17 00:00:00 2001 From: Manuel de Brito Fontes Date: Tue, 31 May 2016 12:22:04 -0400 Subject: [PATCH 4/4] Address comments. Move auth and healthcheck inside nginx package --- ingress/controllers/nginx/.gitignore | 1 + ingress/controllers/nginx/controller.go | 16 +++++++++++--- ingress/controllers/nginx/nginx.tmpl | 12 ++++++++++ .../nginx/{ => nginx}/auth/main.go | 22 +++++++------------ .../nginx/{ => nginx}/auth/main_test.go | 0 .../nginx/{ => nginx}/healthcheck/main.go | 4 ++-- .../{ => nginx}/healthcheck/main_test.go | 0 ingress/controllers/nginx/nginx/nginx.go | 4 +++- 8 files changed, 39 insertions(+), 20 deletions(-) create mode 100644 ingress/controllers/nginx/.gitignore rename ingress/controllers/nginx/{ => nginx}/auth/main.go (89%) rename ingress/controllers/nginx/{ => nginx}/auth/main_test.go (100%) rename ingress/controllers/nginx/{ => nginx}/healthcheck/main.go (94%) rename ingress/controllers/nginx/{ => nginx}/healthcheck/main_test.go (100%) diff --git a/ingress/controllers/nginx/.gitignore b/ingress/controllers/nginx/.gitignore new file mode 100644 index 0000000000..47f069f7a5 --- /dev/null +++ b/ingress/controllers/nginx/.gitignore @@ -0,0 +1 @@ +nginx-ingress-controller diff --git a/ingress/controllers/nginx/controller.go b/ingress/controllers/nginx/controller.go index 3f8776d7d0..81f7f4ea3b 100644 --- a/ingress/controllers/nginx/controller.go +++ b/ingress/controllers/nginx/controller.go @@ -40,8 +40,9 @@ import ( "k8s.io/kubernetes/pkg/util/intstr" "k8s.io/kubernetes/pkg/watch" - "k8s.io/contrib/ingress/controllers/nginx/healthcheck" "k8s.io/contrib/ingress/controllers/nginx/nginx" + "k8s.io/contrib/ingress/controllers/nginx/nginx/auth" + "k8s.io/contrib/ingress/controllers/nginx/nginx/healthcheck" "k8s.io/contrib/ingress/controllers/nginx/nginx/ratelimit" "k8s.io/contrib/ingress/controllers/nginx/nginx/rewrite" ) @@ -584,6 +585,12 @@ func (lbc *loadBalancerController) getUpstreamServers(ngxCfg nginx.NginxConfigur continue } + nginxAuth, err := auth.ParseAnnotations(lbc.client, ing, auth.DefAuthDirectory) + glog.V(3).Infof("nginx auth %v", nginxAuth) + if err != nil { + glog.V(3).Infof("error reading authentication in Ingress %v/%v: %v", ing.GetNamespace(), ing.GetName(), err) + } + rl, err := ratelimit.ParseAnnotations(ing) glog.V(3).Infof("nginx rate limit %v", rl) if err != nil { @@ -617,12 +624,14 @@ func (lbc *loadBalancerController) getUpstreamServers(ngxCfg nginx.NginxConfigur for _, loc := range server.Locations { if loc.Path == rootLocation && nginxPath == rootLocation && loc.IsDefBackend { loc.Upstream = *ups + loc.Auth = *nginxAuth + loc.RateLimit = *rl + locRew, err := rewrite.ParseAnnotations(ing) if err != nil { glog.V(3).Infof("error parsing rewrite annotations for Ingress rule %v/%v: %v", ing.GetNamespace(), ing.GetName(), err) } loc.Redirect = *locRew - loc.RateLimit = *rl addLoc = false continue @@ -645,8 +654,9 @@ func (lbc *loadBalancerController) getUpstreamServers(ngxCfg nginx.NginxConfigur server.Locations = append(server.Locations, &nginx.Location{ Path: nginxPath, Upstream: *ups, - Redirect: *locRew, + Auth: *nginxAuth, RateLimit: *rl, + Redirect: *locRew, }) } } diff --git a/ingress/controllers/nginx/nginx.tmpl b/ingress/controllers/nginx/nginx.tmpl index b12b0c9961..8ede81dd12 100644 --- a/ingress/controllers/nginx/nginx.tmpl +++ b/ingress/controllers/nginx/nginx.tmpl @@ -190,6 +190,18 @@ http { {{ $limits := buildRateLimit $location }} {{- range $limit := $limits }} {{ $limit }}{{ end }} + + {{ if $location.Auth.Secured -}} + {{ if eq $location.Auth.Type "basic" }} + auth_basic "{{ $location.Auth.Realm }}"; + auth_basic_user_file {{ $location.Auth.File }}; + {{ else }} + #TODO: add nginx-http-auth-digest module + auth_digest "{{ $location.Auth.Realm }}"; + auth_digest_user_file {{ $location.Auth.File }}; + {{ end }} + {{- end }} + proxy_set_header Host $host; # Pass Real IP diff --git a/ingress/controllers/nginx/auth/main.go b/ingress/controllers/nginx/nginx/auth/main.go similarity index 89% rename from ingress/controllers/nginx/auth/main.go rename to ingress/controllers/nginx/nginx/auth/main.go index 5169a74c7c..fd957f4e42 100644 --- a/ingress/controllers/nginx/auth/main.go +++ b/ingress/controllers/nginx/nginx/auth/main.go @@ -31,9 +31,9 @@ import ( ) const ( - authType = "ingress-nginx.kubernetes.io/auth-type" - authSecret = "ingress-nginx.kubernetes.io/auth-secret" - authRealm = "ingress-nginx.kubernetes.io/auth-realm" + authType = "ingress.kubernetes.io/auth-type" + authSecret = "ingress.kubernetes.io/auth-secret" + authRealm = "ingress.kubernetes.io/auth-realm" defAuthRealm = "Authentication Required" @@ -61,17 +61,11 @@ var ( // ErrMissingAuthInSecret is returned when there is no auth key in secret data ErrMissingAuthInSecret = errors.New("the secret does not contains the auth key") -) - -// ErrMissingAnnotations is returned when the ingress rule -// does not contains annotations related with authentication -type ErrMissingAnnotations struct { - msg string -} -func (e ErrMissingAnnotations) Error() string { - return e.msg -} + // ErrMissingAnnotations is returned when the ingress rule + // does not contains annotations related with authentication + ErrMissingAnnotations = errors.New("missing authentication annotations") +) // Nginx returns authentication configuration for an Ingress rule type Nginx struct { @@ -121,7 +115,7 @@ func (a ingAnnotations) secretName() (string, error) { // during the authentication process func ParseAnnotations(kubeClient client.Interface, ing *extensions.Ingress, authDir string) (*Nginx, error) { if ing.GetAnnotations() == nil { - return &Nginx{}, ErrMissingAnnotations{"missing authentication annotations"} + return &Nginx{}, ErrMissingAnnotations } at, err := ingAnnotations(ing.GetAnnotations()).authType() diff --git a/ingress/controllers/nginx/auth/main_test.go b/ingress/controllers/nginx/nginx/auth/main_test.go similarity index 100% rename from ingress/controllers/nginx/auth/main_test.go rename to ingress/controllers/nginx/nginx/auth/main_test.go diff --git a/ingress/controllers/nginx/healthcheck/main.go b/ingress/controllers/nginx/nginx/healthcheck/main.go similarity index 94% rename from ingress/controllers/nginx/healthcheck/main.go rename to ingress/controllers/nginx/nginx/healthcheck/main.go index 1dce0b116f..2d19a0c2c0 100644 --- a/ingress/controllers/nginx/healthcheck/main.go +++ b/ingress/controllers/nginx/nginx/healthcheck/main.go @@ -26,8 +26,8 @@ import ( ) const ( - upsMaxFails = "ingress-nginx.kubernetes.io/upstream-max-fails" - upsFailTimeout = "ingress-nginx.kubernetes.io/upstream-fail-timeout" + upsMaxFails = "ingress.kubernetes.io/upstream-max-fails" + upsFailTimeout = "ingress.kubernetes.io/upstream-fail-timeout" ) var ( diff --git a/ingress/controllers/nginx/healthcheck/main_test.go b/ingress/controllers/nginx/nginx/healthcheck/main_test.go similarity index 100% rename from ingress/controllers/nginx/healthcheck/main_test.go rename to ingress/controllers/nginx/nginx/healthcheck/main_test.go diff --git a/ingress/controllers/nginx/nginx/nginx.go b/ingress/controllers/nginx/nginx/nginx.go index 3b1f26dd04..df8268977b 100644 --- a/ingress/controllers/nginx/nginx/nginx.go +++ b/ingress/controllers/nginx/nginx/nginx.go @@ -17,6 +17,7 @@ limitations under the License. package nginx import ( + "k8s.io/contrib/ingress/controllers/nginx/nginx/auth" "k8s.io/contrib/ingress/controllers/nginx/nginx/ratelimit" "k8s.io/contrib/ingress/controllers/nginx/nginx/rewrite" ) @@ -93,8 +94,9 @@ type Location struct { Path string IsDefBackend bool Upstream Upstream - Redirect rewrite.Redirect + Auth auth.Nginx RateLimit ratelimit.RateLimit + Redirect rewrite.Redirect } // LocationByPath sorts location by path