diff --git a/operator/pkg/util/apiclient/wait.go b/operator/pkg/util/apiclient/wait.go index 92eddeb447f7..1c55cb79851d 100644 --- a/operator/pkg/util/apiclient/wait.go +++ b/operator/pkg/util/apiclient/wait.go @@ -36,6 +36,18 @@ const ( APICallRetryInterval = 500 * time.Millisecond ) +var ( + // initialBackoffDuration defines the initial duration for the backoff mechanism, + // set to 5 seconds. This value is used to determine the wait time before retrying + // a failed command. + initialBackoffDuration = 5 * time.Second + + // backoffTimeoutFactor is the factor by which the backoff duration is multiplied + // after each failure. In this case, it is set to 2, meaning the wait time will + // double with each consecutive failure. + backoffTimeoutFactor float64 = 2 +) + // Waiter is an interface for waiting for criteria in Karmada to happen type Waiter interface { // WaitForAPI waits for the API Server's /healthz endpoint to become "ok" @@ -79,9 +91,13 @@ func (w *KarmadaWaiter) WaitForAPI() error { }) } +var aggregateClientFromConfigBuilder = func(karmadaConfig *rest.Config) (aggregator.Interface, error) { + return aggregator.NewForConfig(karmadaConfig) +} + // WaitForAPIService waits for the APIService condition to become "true" func (w *KarmadaWaiter) WaitForAPIService(name string) error { - aggregateClient, err := aggregator.NewForConfig(w.karmadaConfig) + aggregateClient, err := aggregateClientFromConfigBuilder(w.karmadaConfig) if err != nil { return err } @@ -162,20 +178,21 @@ func (w *KarmadaWaiter) SetTimeout(timeout time.Duration) { w.timeout = timeout } -// TryRunCommand runs a function a maximum of failureThreshold times, and retries on error. If failureThreshold is hit; the last error is returned +// TryRunCommand runs a function a maximum of failureThreshold times, and +// retries on error. If failureThreshold is hit; the last error is returned. func TryRunCommand(f func() error, failureThreshold int) error { backoff := wait.Backoff{ - Duration: 5 * time.Second, - Factor: 2, // double the timeout for every failure + Duration: initialBackoffDuration, + Factor: backoffTimeoutFactor, Steps: failureThreshold, } return wait.ExponentialBackoff(backoff, func() (bool, error) { err := f() if err != nil { - // Retry until the timeout + // Retry until the timeout. return false, nil } - // The last f() call was a success, return cleanly + // The last f() call was a success, return cleanly. return true, nil }) } diff --git a/operator/pkg/util/apiclient/wait_test.go b/operator/pkg/util/apiclient/wait_test.go new file mode 100644 index 000000000000..c1d7a32cf565 --- /dev/null +++ b/operator/pkg/util/apiclient/wait_test.go @@ -0,0 +1,446 @@ +/* +Copyright 2024 The Karmada Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package apiclient + +import ( + "context" + "errors" + "fmt" + "net/http" + "testing" + "time" + + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/labels" + "k8s.io/apimachinery/pkg/runtime" + clientset "k8s.io/client-go/kubernetes" + fakeclientset "k8s.io/client-go/kubernetes/fake" + "k8s.io/client-go/rest" + fakerest "k8s.io/client-go/rest/fake" + apiregistrationv1 "k8s.io/kube-aggregator/pkg/apis/apiregistration/v1" + aggregator "k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset" + fakeAggregator "k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset/fake" + + "github.com/karmada-io/karmada/operator/pkg/constants" +) + +func TestWaitForAPI(t *testing.T) { + tests := []struct { + name string + karmadaWriter *KarmadaWaiter + wantErr bool + }{ + { + name: "WaitForAPI_WaitingForAPIServerHealthyStatus_Timeout", + karmadaWriter: &KarmadaWaiter{ + karmadaConfig: &rest.Config{}, + client: &MockK8SRESTClient{ + RESTClientConnector: &fakerest.RESTClient{ + NegotiatedSerializer: runtime.NewSimpleNegotiatedSerializer(runtime.SerializerInfo{}), + Client: fakerest.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { + return nil, fmt.Errorf("unexpected error, endpoint %s does not exist", req.URL.Path) + }), + }, + }, + timeout: time.Second, + }, + wantErr: true, + }, + { + name: "WaitForAPI_WaitingForAPIServerHealthyStatus_APIServerIsHealthy", + karmadaWriter: &KarmadaWaiter{ + karmadaConfig: &rest.Config{}, + client: &MockK8SRESTClient{ + RESTClientConnector: &fakerest.RESTClient{ + NegotiatedSerializer: runtime.NewSimpleNegotiatedSerializer(runtime.SerializerInfo{}), + Client: fakerest.CreateHTTPClient(func(req *http.Request) (*http.Response, error) { + if req.URL.Path == "/healthz" { + // Return a fake 200 OK response. + return &http.Response{ + StatusCode: http.StatusOK, + Body: http.NoBody, + }, nil + } + return nil, fmt.Errorf("unexpected error, endpoint %s does not exist", req.URL.Path) + }), + }, + }, + timeout: time.Millisecond, + }, + wantErr: false, + }, + } + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + err := test.karmadaWriter.WaitForAPI() + if err == nil && test.wantErr { + t.Errorf("expected an error, but got none") + } + if err != nil && !test.wantErr { + t.Errorf("unexpected error, got: %v", err) + } + }) + } +} + +func TestWaitForAPIService(t *testing.T) { + name := "karmada-demo-apiservice" + tests := []struct { + name string + karmadaWriter *KarmadaWaiter + apiService *apiregistrationv1.APIService + client aggregator.Interface + prep func(aggregator.Interface, *apiregistrationv1.APIService) error + wantErr bool + }{ + { + name: "WaitForAPIService_WaitingForKarmadaAPIServiceAvailableStatus_Timeout", + karmadaWriter: &KarmadaWaiter{ + karmadaConfig: &rest.Config{}, + timeout: time.Second, + }, + apiService: &apiregistrationv1.APIService{ + ObjectMeta: metav1.ObjectMeta{ + Name: name, + }, + Spec: apiregistrationv1.APIServiceSpec{ + Service: &apiregistrationv1.ServiceReference{ + Name: "karmada-demo-service", + Namespace: "test", + }, + Version: "v1beta1", + }, + }, + client: fakeAggregator.NewSimpleClientset(), + prep: func(client aggregator.Interface, _ *apiregistrationv1.APIService) error { + aggregateClientFromConfigBuilder = func(*rest.Config) (aggregator.Interface, error) { + return client, nil + } + return nil + }, + wantErr: true, + }, + { + name: "WaitForAPIService_WaitingForKarmadaAPIServiceAvailableStatus_KarmadaAPIServiceIsAvailable", + karmadaWriter: &KarmadaWaiter{ + karmadaConfig: &rest.Config{}, + timeout: time.Millisecond, + }, + apiService: &apiregistrationv1.APIService{ + ObjectMeta: metav1.ObjectMeta{ + Name: name, + }, + Spec: apiregistrationv1.APIServiceSpec{ + Service: &apiregistrationv1.ServiceReference{ + Name: "karmada-demo-service", + Namespace: "test", + }, + Version: "v1beta1", + }, + }, + client: fakeAggregator.NewSimpleClientset(), + prep: func(client aggregator.Interface, apiService *apiregistrationv1.APIService) error { + apiServiceCreated, err := client.ApiregistrationV1().APIServices().Create(context.TODO(), apiService, metav1.CreateOptions{}) + if err != nil { + return fmt.Errorf("faield to create api service %s, got err: %v", apiService.Name, err) + } + apiServiceCreated.Status = apiregistrationv1.APIServiceStatus{ + Conditions: []apiregistrationv1.APIServiceCondition{ + { + Type: apiregistrationv1.Available, + Status: apiregistrationv1.ConditionTrue, + }, + }, + } + if _, err = client.ApiregistrationV1().APIServices().Update(context.TODO(), apiServiceCreated, metav1.UpdateOptions{}); err != nil { + return fmt.Errorf("failed to update api service with available status, got err: %v", err) + } + aggregateClientFromConfigBuilder = func(*rest.Config) (aggregator.Interface, error) { + return client, nil + } + return nil + }, + wantErr: false, + }, + } + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + if err := test.prep(test.client, test.apiService); err != nil { + t.Errorf("failed to prep waiting for Karmada API Service, got err: %v", err) + } + err := test.karmadaWriter.WaitForAPIService(name) + if err == nil && test.wantErr { + t.Errorf("expected an error, but got none") + } + if err != nil && !test.wantErr { + t.Errorf("unexpected error, got: %v", err) + } + }) + } +} + +func TestWaitForPods(t *testing.T) { + name, namespace := "karmada-demo-apiserver", "test" + karmadaAPIServerLabels := labels.Set{"karmada-app": constants.KarmadaAPIServer} + var replicas int32 = 2 + tests := []struct { + name string + karmadaWriter *KarmadaWaiter + prep func(client clientset.Interface) error + wantErr bool + }{ + { + name: "WaitForPods_WaitingForAllKarmadaAPIServerPods_Timeout", + karmadaWriter: &KarmadaWaiter{ + karmadaConfig: &rest.Config{}, + client: fakeclientset.NewSimpleClientset(), + timeout: time.Second, + }, + prep: func(client clientset.Interface) error { + _, err := CreatePods(client, namespace, name, replicas, karmadaAPIServerLabels, false) + if err != nil { + return fmt.Errorf("failed to create pods, got err: %v", err) + } + return nil + }, + wantErr: true, + }, + { + name: "WaitForPods_WaitingForAllKarmadaAPIServerPods_AllAreUpAndRunning", + karmadaWriter: &KarmadaWaiter{ + karmadaConfig: &rest.Config{}, + client: fakeclientset.NewSimpleClientset(), + timeout: time.Second * 2, + }, + prep: func(client clientset.Interface) error { + pods, err := CreatePods(client, namespace, name, replicas, karmadaAPIServerLabels, false) + if err != nil { + return fmt.Errorf("failed to create pods, got err: %v", err) + } + time.AfterFunc(time.Second, func() { + for _, pod := range pods { + if err := UpdatePodStatus(client, pod); err != nil { + fmt.Printf("failed to update pod status, got err: %v", err) + return + } + } + }) + return nil + }, + wantErr: false, + }, + } + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + if err := test.prep(test.karmadaWriter.client); err != nil { + t.Errorf("failed to prep before waiting for all Karmada APIServer pods , got err: %v", err) + } + err := test.karmadaWriter.WaitForPods(karmadaAPIServerLabels.String(), namespace) + if err == nil && test.wantErr { + t.Errorf("expected an error, but got none") + } + if err != nil && !test.wantErr { + t.Errorf("unexpected error, got: %v", err) + } + }) + } +} + +func TestWaitForSomePods(t *testing.T) { + name, namespace := "karmada-demo-apiserver", "test" + karmadaAPIServerLabels := labels.Set{"karmada-app": constants.KarmadaAPIServer} + var replicas int32 = 2 + tests := []struct { + name string + karmadaWriter *KarmadaWaiter + prep func(client clientset.Interface) error + wantErr bool + }{ + { + name: "WaitForSomePods_WaitingForSomeKarmadaAPIServerPods_Timeout", + karmadaWriter: &KarmadaWaiter{ + karmadaConfig: &rest.Config{}, + client: fakeclientset.NewSimpleClientset(), + timeout: time.Second, + }, + prep: func(client clientset.Interface) error { + _, err := CreatePods(client, namespace, name, replicas, karmadaAPIServerLabels, false) + if err != nil { + return fmt.Errorf("failed to create pods, got err: %v", err) + } + return nil + }, + wantErr: true, + }, + { + name: "WaitForSomePods_WaitingForSomeKarmadaAPIServerPods_SomeAreUpAndRunning", + karmadaWriter: &KarmadaWaiter{ + karmadaConfig: &rest.Config{}, + client: fakeclientset.NewSimpleClientset(), + timeout: time.Millisecond, + }, + prep: func(client clientset.Interface) error { + pods, err := CreatePods(client, namespace, name, replicas, karmadaAPIServerLabels, false) + if err != nil { + return fmt.Errorf("failed to create pods, got err: %v", err) + } + for _, pod := range pods[:1] { + if err := UpdatePodStatus(client, pod); err != nil { + return fmt.Errorf("failed to update pod status, got err: %v", err) + } + } + return nil + }, + wantErr: false, + }, + } + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + if err := test.prep(test.karmadaWriter.client); err != nil { + t.Errorf("failed to prep before waiting for some Karmada APIServer pods , got err: %v", err) + } + err := test.karmadaWriter.WaitForSomePods(karmadaAPIServerLabels.String(), namespace, 1) + if err == nil && test.wantErr { + t.Errorf("expected an error, but got none") + } + if err != nil && !test.wantErr { + t.Errorf("unexpected error, got: %v", err) + } + }) + } +} + +func TestTryRunCommand(t *testing.T) { + tests := []struct { + name string + failureThreshold int + targetFunc func() error + prep func() error + wantErr bool + }{ + { + name: "TryRunCommand_HitTheFailureThreshold_CommandTimedOut", + failureThreshold: 2, + targetFunc: func() error { + return errors.New("unexpected error") + }, + prep: func() error { + initialBackoffDuration = time.Millisecond + return nil + }, + wantErr: true, + }, + { + name: "TryRunCommand_BelowFailureThreshold_CommandRunSuccessfully", + failureThreshold: 2, + targetFunc: func() error { return nil }, + prep: func() error { + initialBackoffDuration = time.Millisecond + return nil + }, + wantErr: false, + }, + } + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + if err := test.prep(); err != nil { + t.Errorf("failed to prep before trying to running command, got err: %v", err) + } + err := TryRunCommand(test.targetFunc, test.failureThreshold) + if err == nil && test.wantErr { + t.Errorf("expected an error, but got none") + } + if err != nil && !test.wantErr { + t.Errorf("unexpected error, got: %v", err) + } + }) + } +} + +func TestIsPodRunning(t *testing.T) { + tests := []struct { + name string + pod *corev1.Pod + want bool + }{ + { + name: "IsPodRunning_PodInPendingState_PodIsNotRunningYet", + pod: &corev1.Pod{ + Status: corev1.PodStatus{ + Phase: corev1.PodPending, + }, + }, + want: false, + }, + { + name: "IsPodRunning_WithDeletionTimestamp_PodIsNotRunningYet", + pod: &corev1.Pod{ + ObjectMeta: metav1.ObjectMeta{ + DeletionTimestamp: &metav1.Time{Time: time.Now()}, + }, + Status: corev1.PodStatus{ + Phase: corev1.PodRunning, + }, + }, + want: false, + }, + { + name: "IsPodRunning_PodReadyConditionReadinessIsFalse_PodIsNotRunningYet", + pod: &corev1.Pod{ + ObjectMeta: metav1.ObjectMeta{ + DeletionTimestamp: nil, + }, + Status: corev1.PodStatus{ + Phase: corev1.PodRunning, + Conditions: []corev1.PodCondition{ + { + Type: corev1.PodReady, + Status: corev1.ConditionFalse, + }, + }, + }, + }, + want: false, + }, + { + name: "IsPodRunning_PodSatisfyAllRunningConditions_PodIsAlreadyRunning", + pod: &corev1.Pod{ + ObjectMeta: metav1.ObjectMeta{ + DeletionTimestamp: nil, + }, + Status: corev1.PodStatus{ + Phase: corev1.PodRunning, + Conditions: []corev1.PodCondition{ + { + Type: corev1.PodReady, + Status: corev1.ConditionTrue, + }, + }, + }, + }, + want: true, + }, + } + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + if got := isPodRunning(*test.pod); got != test.want { + t.Errorf("expected pod running status %t, but got %t", test.want, got) + } + }) + } +} diff --git a/vendor/k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset/fake/clientset_generated.go b/vendor/k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset/fake/clientset_generated.go new file mode 100644 index 000000000000..e48af65d3fbb --- /dev/null +++ b/vendor/k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset/fake/clientset_generated.go @@ -0,0 +1,92 @@ +/* +Copyright The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by client-gen. DO NOT EDIT. + +package fake + +import ( + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/watch" + "k8s.io/client-go/discovery" + fakediscovery "k8s.io/client-go/discovery/fake" + "k8s.io/client-go/testing" + clientset "k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset" + apiregistrationv1 "k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset/typed/apiregistration/v1" + fakeapiregistrationv1 "k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset/typed/apiregistration/v1/fake" + apiregistrationv1beta1 "k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset/typed/apiregistration/v1beta1" + fakeapiregistrationv1beta1 "k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset/typed/apiregistration/v1beta1/fake" +) + +// NewSimpleClientset returns a clientset that will respond with the provided objects. +// It's backed by a very simple object tracker that processes creates, updates and deletions as-is, +// without applying any validations and/or defaults. It shouldn't be considered a replacement +// for a real clientset and is mostly useful in simple unit tests. +func NewSimpleClientset(objects ...runtime.Object) *Clientset { + o := testing.NewObjectTracker(scheme, codecs.UniversalDecoder()) + for _, obj := range objects { + if err := o.Add(obj); err != nil { + panic(err) + } + } + + cs := &Clientset{tracker: o} + cs.discovery = &fakediscovery.FakeDiscovery{Fake: &cs.Fake} + cs.AddReactor("*", "*", testing.ObjectReaction(o)) + cs.AddWatchReactor("*", func(action testing.Action) (handled bool, ret watch.Interface, err error) { + gvr := action.GetResource() + ns := action.GetNamespace() + watch, err := o.Watch(gvr, ns) + if err != nil { + return false, nil, err + } + return true, watch, nil + }) + + return cs +} + +// Clientset implements clientset.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 Clientset struct { + testing.Fake + discovery *fakediscovery.FakeDiscovery + tracker testing.ObjectTracker +} + +func (c *Clientset) Discovery() discovery.DiscoveryInterface { + return c.discovery +} + +func (c *Clientset) Tracker() testing.ObjectTracker { + return c.tracker +} + +var ( + _ clientset.Interface = &Clientset{} + _ testing.FakeClient = &Clientset{} +) + +// ApiregistrationV1 retrieves the ApiregistrationV1Client +func (c *Clientset) ApiregistrationV1() apiregistrationv1.ApiregistrationV1Interface { + return &fakeapiregistrationv1.FakeApiregistrationV1{Fake: &c.Fake} +} + +// ApiregistrationV1beta1 retrieves the ApiregistrationV1beta1Client +func (c *Clientset) ApiregistrationV1beta1() apiregistrationv1beta1.ApiregistrationV1beta1Interface { + return &fakeapiregistrationv1beta1.FakeApiregistrationV1beta1{Fake: &c.Fake} +} diff --git a/vendor/k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset/fake/doc.go b/vendor/k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset/fake/doc.go new file mode 100644 index 000000000000..9b99e7167091 --- /dev/null +++ b/vendor/k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset/fake/doc.go @@ -0,0 +1,20 @@ +/* +Copyright The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by client-gen. DO NOT EDIT. + +// This package has the automatically generated fake clientset. +package fake diff --git a/vendor/k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset/fake/register.go b/vendor/k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset/fake/register.go new file mode 100644 index 000000000000..880c67a3979a --- /dev/null +++ b/vendor/k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset/fake/register.go @@ -0,0 +1,58 @@ +/* +Copyright The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by client-gen. DO NOT EDIT. + +package fake + +import ( + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + runtime "k8s.io/apimachinery/pkg/runtime" + schema "k8s.io/apimachinery/pkg/runtime/schema" + serializer "k8s.io/apimachinery/pkg/runtime/serializer" + utilruntime "k8s.io/apimachinery/pkg/util/runtime" + apiregistrationv1 "k8s.io/kube-aggregator/pkg/apis/apiregistration/v1" + apiregistrationv1beta1 "k8s.io/kube-aggregator/pkg/apis/apiregistration/v1beta1" +) + +var scheme = runtime.NewScheme() +var codecs = serializer.NewCodecFactory(scheme) + +var localSchemeBuilder = runtime.SchemeBuilder{ + apiregistrationv1.AddToScheme, + apiregistrationv1beta1.AddToScheme, +} + +// AddToScheme adds all types of this clientset into the given scheme. This allows composition +// of clientsets, like in: +// +// import ( +// "k8s.io/client-go/kubernetes" +// clientsetscheme "k8s.io/client-go/kubernetes/scheme" +// aggregatorclientsetscheme "k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset/scheme" +// ) +// +// kclientset, _ := kubernetes.NewForConfig(c) +// _ = aggregatorclientsetscheme.AddToScheme(clientsetscheme.Scheme) +// +// After this, RawExtensions in Kubernetes types will serialize kube-aggregator types +// correctly. +var AddToScheme = localSchemeBuilder.AddToScheme + +func init() { + v1.AddToGroupVersion(scheme, schema.GroupVersion{Version: "v1"}) + utilruntime.Must(AddToScheme(scheme)) +} diff --git a/vendor/k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset/typed/apiregistration/v1/fake/doc.go b/vendor/k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset/typed/apiregistration/v1/fake/doc.go new file mode 100644 index 000000000000..16f44399065e --- /dev/null +++ b/vendor/k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset/typed/apiregistration/v1/fake/doc.go @@ -0,0 +1,20 @@ +/* +Copyright The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by client-gen. DO NOT EDIT. + +// Package fake has the automatically generated clients. +package fake diff --git a/vendor/k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset/typed/apiregistration/v1/fake/fake_apiregistration_client.go b/vendor/k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset/typed/apiregistration/v1/fake/fake_apiregistration_client.go new file mode 100644 index 000000000000..3e563e6f07dd --- /dev/null +++ b/vendor/k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset/typed/apiregistration/v1/fake/fake_apiregistration_client.go @@ -0,0 +1,40 @@ +/* +Copyright The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by client-gen. DO NOT EDIT. + +package fake + +import ( + rest "k8s.io/client-go/rest" + testing "k8s.io/client-go/testing" + v1 "k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset/typed/apiregistration/v1" +) + +type FakeApiregistrationV1 struct { + *testing.Fake +} + +func (c *FakeApiregistrationV1) APIServices() v1.APIServiceInterface { + return &FakeAPIServices{c} +} + +// RESTClient returns a RESTClient that is used to communicate +// with API server by this client implementation. +func (c *FakeApiregistrationV1) RESTClient() rest.Interface { + var ret *rest.RESTClient + return ret +} diff --git a/vendor/k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset/typed/apiregistration/v1/fake/fake_apiservice.go b/vendor/k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset/typed/apiregistration/v1/fake/fake_apiservice.go new file mode 100644 index 000000000000..88c87954a5fd --- /dev/null +++ b/vendor/k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset/typed/apiregistration/v1/fake/fake_apiservice.go @@ -0,0 +1,132 @@ +/* +Copyright The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by client-gen. DO NOT EDIT. + +package fake + +import ( + "context" + + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + labels "k8s.io/apimachinery/pkg/labels" + types "k8s.io/apimachinery/pkg/types" + watch "k8s.io/apimachinery/pkg/watch" + testing "k8s.io/client-go/testing" + v1 "k8s.io/kube-aggregator/pkg/apis/apiregistration/v1" +) + +// FakeAPIServices implements APIServiceInterface +type FakeAPIServices struct { + Fake *FakeApiregistrationV1 +} + +var apiservicesResource = v1.SchemeGroupVersion.WithResource("apiservices") + +var apiservicesKind = v1.SchemeGroupVersion.WithKind("APIService") + +// Get takes name of the aPIService, and returns the corresponding aPIService object, and an error if there is any. +func (c *FakeAPIServices) Get(ctx context.Context, name string, options metav1.GetOptions) (result *v1.APIService, err error) { + obj, err := c.Fake. + Invokes(testing.NewRootGetAction(apiservicesResource, name), &v1.APIService{}) + if obj == nil { + return nil, err + } + return obj.(*v1.APIService), err +} + +// List takes label and field selectors, and returns the list of APIServices that match those selectors. +func (c *FakeAPIServices) List(ctx context.Context, opts metav1.ListOptions) (result *v1.APIServiceList, err error) { + obj, err := c.Fake. + Invokes(testing.NewRootListAction(apiservicesResource, apiservicesKind, opts), &v1.APIServiceList{}) + if obj == nil { + return nil, err + } + + label, _, _ := testing.ExtractFromListOptions(opts) + if label == nil { + label = labels.Everything() + } + list := &v1.APIServiceList{ListMeta: obj.(*v1.APIServiceList).ListMeta} + for _, item := range obj.(*v1.APIServiceList).Items { + if label.Matches(labels.Set(item.Labels)) { + list.Items = append(list.Items, item) + } + } + return list, err +} + +// Watch returns a watch.Interface that watches the requested aPIServices. +func (c *FakeAPIServices) Watch(ctx context.Context, opts metav1.ListOptions) (watch.Interface, error) { + return c.Fake. + InvokesWatch(testing.NewRootWatchAction(apiservicesResource, opts)) +} + +// Create takes the representation of a aPIService and creates it. Returns the server's representation of the aPIService, and an error, if there is any. +func (c *FakeAPIServices) Create(ctx context.Context, aPIService *v1.APIService, opts metav1.CreateOptions) (result *v1.APIService, err error) { + obj, err := c.Fake. + Invokes(testing.NewRootCreateAction(apiservicesResource, aPIService), &v1.APIService{}) + if obj == nil { + return nil, err + } + return obj.(*v1.APIService), err +} + +// Update takes the representation of a aPIService and updates it. Returns the server's representation of the aPIService, and an error, if there is any. +func (c *FakeAPIServices) Update(ctx context.Context, aPIService *v1.APIService, opts metav1.UpdateOptions) (result *v1.APIService, err error) { + obj, err := c.Fake. + Invokes(testing.NewRootUpdateAction(apiservicesResource, aPIService), &v1.APIService{}) + if obj == nil { + return nil, err + } + return obj.(*v1.APIService), err +} + +// UpdateStatus was generated because the type contains a Status member. +// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus(). +func (c *FakeAPIServices) UpdateStatus(ctx context.Context, aPIService *v1.APIService, opts metav1.UpdateOptions) (*v1.APIService, error) { + obj, err := c.Fake. + Invokes(testing.NewRootUpdateSubresourceAction(apiservicesResource, "status", aPIService), &v1.APIService{}) + if obj == nil { + return nil, err + } + return obj.(*v1.APIService), err +} + +// Delete takes name of the aPIService and deletes it. Returns an error if one occurs. +func (c *FakeAPIServices) Delete(ctx context.Context, name string, opts metav1.DeleteOptions) error { + _, err := c.Fake. + Invokes(testing.NewRootDeleteActionWithOptions(apiservicesResource, name, opts), &v1.APIService{}) + return err +} + +// DeleteCollection deletes a collection of objects. +func (c *FakeAPIServices) DeleteCollection(ctx context.Context, opts metav1.DeleteOptions, listOpts metav1.ListOptions) error { + action := testing.NewRootDeleteCollectionAction(apiservicesResource, listOpts) + + _, err := c.Fake.Invokes(action, &v1.APIServiceList{}) + return err +} + +// Patch applies the patch and returns the patched aPIService. +func (c *FakeAPIServices) Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts metav1.PatchOptions, subresources ...string) (result *v1.APIService, err error) { + obj, err := c.Fake. + Invokes(testing.NewRootPatchSubresourceAction(apiservicesResource, name, pt, data, subresources...), &v1.APIService{}) + if obj == nil { + return nil, err + } + return obj.(*v1.APIService), err +} diff --git a/vendor/k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset/typed/apiregistration/v1beta1/fake/doc.go b/vendor/k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset/typed/apiregistration/v1beta1/fake/doc.go new file mode 100644 index 000000000000..16f44399065e --- /dev/null +++ b/vendor/k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset/typed/apiregistration/v1beta1/fake/doc.go @@ -0,0 +1,20 @@ +/* +Copyright The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by client-gen. DO NOT EDIT. + +// Package fake has the automatically generated clients. +package fake diff --git a/vendor/k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset/typed/apiregistration/v1beta1/fake/fake_apiregistration_client.go b/vendor/k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset/typed/apiregistration/v1beta1/fake/fake_apiregistration_client.go new file mode 100644 index 000000000000..9b32316af6ae --- /dev/null +++ b/vendor/k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset/typed/apiregistration/v1beta1/fake/fake_apiregistration_client.go @@ -0,0 +1,40 @@ +/* +Copyright The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by client-gen. DO NOT EDIT. + +package fake + +import ( + rest "k8s.io/client-go/rest" + testing "k8s.io/client-go/testing" + v1beta1 "k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset/typed/apiregistration/v1beta1" +) + +type FakeApiregistrationV1beta1 struct { + *testing.Fake +} + +func (c *FakeApiregistrationV1beta1) APIServices() v1beta1.APIServiceInterface { + return &FakeAPIServices{c} +} + +// RESTClient returns a RESTClient that is used to communicate +// with API server by this client implementation. +func (c *FakeApiregistrationV1beta1) RESTClient() rest.Interface { + var ret *rest.RESTClient + return ret +} diff --git a/vendor/k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset/typed/apiregistration/v1beta1/fake/fake_apiservice.go b/vendor/k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset/typed/apiregistration/v1beta1/fake/fake_apiservice.go new file mode 100644 index 000000000000..4c5a1868a9bf --- /dev/null +++ b/vendor/k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset/typed/apiregistration/v1beta1/fake/fake_apiservice.go @@ -0,0 +1,132 @@ +/* +Copyright The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by client-gen. DO NOT EDIT. + +package fake + +import ( + "context" + + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + labels "k8s.io/apimachinery/pkg/labels" + types "k8s.io/apimachinery/pkg/types" + watch "k8s.io/apimachinery/pkg/watch" + testing "k8s.io/client-go/testing" + v1beta1 "k8s.io/kube-aggregator/pkg/apis/apiregistration/v1beta1" +) + +// FakeAPIServices implements APIServiceInterface +type FakeAPIServices struct { + Fake *FakeApiregistrationV1beta1 +} + +var apiservicesResource = v1beta1.SchemeGroupVersion.WithResource("apiservices") + +var apiservicesKind = v1beta1.SchemeGroupVersion.WithKind("APIService") + +// Get takes name of the aPIService, and returns the corresponding aPIService object, and an error if there is any. +func (c *FakeAPIServices) Get(ctx context.Context, name string, options v1.GetOptions) (result *v1beta1.APIService, err error) { + obj, err := c.Fake. + Invokes(testing.NewRootGetAction(apiservicesResource, name), &v1beta1.APIService{}) + if obj == nil { + return nil, err + } + return obj.(*v1beta1.APIService), err +} + +// List takes label and field selectors, and returns the list of APIServices that match those selectors. +func (c *FakeAPIServices) List(ctx context.Context, opts v1.ListOptions) (result *v1beta1.APIServiceList, err error) { + obj, err := c.Fake. + Invokes(testing.NewRootListAction(apiservicesResource, apiservicesKind, opts), &v1beta1.APIServiceList{}) + if obj == nil { + return nil, err + } + + label, _, _ := testing.ExtractFromListOptions(opts) + if label == nil { + label = labels.Everything() + } + list := &v1beta1.APIServiceList{ListMeta: obj.(*v1beta1.APIServiceList).ListMeta} + for _, item := range obj.(*v1beta1.APIServiceList).Items { + if label.Matches(labels.Set(item.Labels)) { + list.Items = append(list.Items, item) + } + } + return list, err +} + +// Watch returns a watch.Interface that watches the requested aPIServices. +func (c *FakeAPIServices) Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error) { + return c.Fake. + InvokesWatch(testing.NewRootWatchAction(apiservicesResource, opts)) +} + +// Create takes the representation of a aPIService and creates it. Returns the server's representation of the aPIService, and an error, if there is any. +func (c *FakeAPIServices) Create(ctx context.Context, aPIService *v1beta1.APIService, opts v1.CreateOptions) (result *v1beta1.APIService, err error) { + obj, err := c.Fake. + Invokes(testing.NewRootCreateAction(apiservicesResource, aPIService), &v1beta1.APIService{}) + if obj == nil { + return nil, err + } + return obj.(*v1beta1.APIService), err +} + +// Update takes the representation of a aPIService and updates it. Returns the server's representation of the aPIService, and an error, if there is any. +func (c *FakeAPIServices) Update(ctx context.Context, aPIService *v1beta1.APIService, opts v1.UpdateOptions) (result *v1beta1.APIService, err error) { + obj, err := c.Fake. + Invokes(testing.NewRootUpdateAction(apiservicesResource, aPIService), &v1beta1.APIService{}) + if obj == nil { + return nil, err + } + return obj.(*v1beta1.APIService), err +} + +// UpdateStatus was generated because the type contains a Status member. +// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus(). +func (c *FakeAPIServices) UpdateStatus(ctx context.Context, aPIService *v1beta1.APIService, opts v1.UpdateOptions) (*v1beta1.APIService, error) { + obj, err := c.Fake. + Invokes(testing.NewRootUpdateSubresourceAction(apiservicesResource, "status", aPIService), &v1beta1.APIService{}) + if obj == nil { + return nil, err + } + return obj.(*v1beta1.APIService), err +} + +// Delete takes name of the aPIService and deletes it. Returns an error if one occurs. +func (c *FakeAPIServices) Delete(ctx context.Context, name string, opts v1.DeleteOptions) error { + _, err := c.Fake. + Invokes(testing.NewRootDeleteActionWithOptions(apiservicesResource, name, opts), &v1beta1.APIService{}) + return err +} + +// DeleteCollection deletes a collection of objects. +func (c *FakeAPIServices) DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error { + action := testing.NewRootDeleteCollectionAction(apiservicesResource, listOpts) + + _, err := c.Fake.Invokes(action, &v1beta1.APIServiceList{}) + return err +} + +// Patch applies the patch and returns the patched aPIService. +func (c *FakeAPIServices) Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v1beta1.APIService, err error) { + obj, err := c.Fake. + Invokes(testing.NewRootPatchSubresourceAction(apiservicesResource, name, pt, data, subresources...), &v1beta1.APIService{}) + if obj == nil { + return nil, err + } + return obj.(*v1beta1.APIService), err +} diff --git a/vendor/modules.txt b/vendor/modules.txt index 99b354eacd4d..288c3285e18a 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -1629,9 +1629,12 @@ k8s.io/kube-aggregator/pkg/apis/apiregistration/validation k8s.io/kube-aggregator/pkg/apiserver k8s.io/kube-aggregator/pkg/apiserver/scheme k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset +k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset/fake k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset/scheme k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset/typed/apiregistration/v1 +k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset/typed/apiregistration/v1/fake k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset/typed/apiregistration/v1beta1 +k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset/typed/apiregistration/v1beta1/fake k8s.io/kube-aggregator/pkg/client/informers/externalversions k8s.io/kube-aggregator/pkg/client/informers/externalversions/apiregistration k8s.io/kube-aggregator/pkg/client/informers/externalversions/apiregistration/v1