From 370ef1a8c09f72ec724d6b0921aa3ca0c1c52dbf Mon Sep 17 00:00:00 2001 From: Amit Kumar Das Date: Tue, 26 May 2020 20:29:39 +0530 Subject: [PATCH] feat(gctl): #142 add indefinite retry option during metac startup (#143) This commit closes https://github.com/AmitKumarDas/metac/issues/142 A new boolean flag named 'retry-indefinitely-to-start' is added that lets metac to retry indefinitely to start all the configured generic controllers. When this flag is set to true, retries happen even when one or more configured kubernetes custom resource definitions are not available at the cluster. Once these custom definitions are available & discovered by metac, this retry stops completely. When this flag is not set which is also the default setting, metac binary panics (i.e. metac container stops running) if any of the configured controllers make use of custom resources whose definitions are not yet available in the cluster. The binary panics after exhausting the configured timeout (which defaults to 30 minutes). This feature help teams to manage the transient phases during controller upgrades. One such scenario is when these upgraded controllers make use of new custom resource definition(s) that are yet to be applied against the cluster. Signed-off-by: AmitKumarDas --- Makefile | 2 +- controller/generic/metacontroller.go | 150 ++++++++----- controller/generic/metacontroller_test.go | 18 +- go.mod | 1 - server/server.go | 11 +- start/start.go | 13 +- ...set_status_on_cr_that_exists_later_test.go | 201 ++++++++++++++++++ test/integration/framework/apply.go | 2 +- test/integration/framework/crd.go | 2 +- test/integration/framework/fixture.go | 10 +- test/integration/framework/metacontroller.go | 2 +- test/integration/framework/start.go | 30 +-- 12 files changed, 351 insertions(+), 91 deletions(-) create mode 100644 test/integration/config-mode/set_status_on_cr_that_exists_later_test.go diff --git a/Makefile b/Makefile index 2e0b306..e9aba51 100644 --- a/Makefile +++ b/Makefile @@ -109,7 +109,7 @@ integration-dependencies: all .PHONY: integration-test integration-test: integration-dependencies @go test ./test/integration/... \ - -v -timeout=10m -args --logtostderr --alsologtostderr -v=1 + -v -short -timeout=10m -args --logtostderr --alsologtostderr -v=1 # integration-test-crd-mode runs tests with metac loading # metacontrollers as kubernetes custom resources diff --git a/controller/generic/metacontroller.go b/controller/generic/metacontroller.go index 935099c..5efc73f 100644 --- a/controller/generic/metacontroller.go +++ b/controller/generic/metacontroller.go @@ -17,6 +17,8 @@ limitations under the License. package generic import ( + "fmt" + "strings" "sync" "time" @@ -82,19 +84,15 @@ type ConfigMetaController struct { // controllers Configs []*v1alpha1.GenericController - // Total timeout for any condition to succeed. - // - // NOTE: - // This is currently used to load config that is required - // to run Metac. - WaitTimeoutForCondition time.Duration + // This will allow executing start logic to be retried + // indefinitely till all the watch controllers are started + RetryIndefinitelyUntilSucceed *bool - // Interval between retries for any condition to succeed. - // - // NOTE: - // This is currently used to load config that is required - // to run Metac - WaitIntervalForCondition time.Duration + // Maximum time to wait to start all watch controllers + WaitTimeoutForStartAttempt time.Duration + + // Interval between retries to start all watch controllers + WaitIntervalBetweenRestarts time.Duration opts []ConfigMetaControllerOption err error @@ -106,8 +104,29 @@ type ConfigMetaController struct { // This follows **functional options** pattern type ConfigMetaControllerOption func(*ConfigMetaController) error -// SetMetaControllerConfigLoadFn sets the config loader function -func SetMetaControllerConfigLoadFn( +// SetMetacConfigToRetryIndefinitelyForStart will let this +// controller to retry indefinitely till all its watch controllers +// are started +// +// NOTE: +// Indefinite retry is set only when the provided flag is true +func SetMetacConfigToRetryIndefinitelyForStart(enabled *bool) ConfigMetaControllerOption { + return func(c *ConfigMetaController) error { + // indefinite retry is set only if enabled is true + if enabled == nil || !*enabled { + return nil + } + // We are not bothered about performance. We do not + // need to be fast. We can be lazy but not to the + // extent of sleeping for hours. + c.WaitIntervalBetweenRestarts = 1 * time.Minute + c.RetryIndefinitelyUntilSucceed = k8s.BoolPtr(true) + return nil + } +} + +// SetMetacConfigLoadFn sets the config loader function +func SetMetacConfigLoadFn( fn func() ([]*v1alpha1.GenericController, error), ) ConfigMetaControllerOption { return func(c *ConfigMetaController) error { @@ -116,8 +135,8 @@ func SetMetaControllerConfigLoadFn( } } -// SetMetaControllerConfigPath sets the config path -func SetMetaControllerConfigPath(path string) ConfigMetaControllerOption { +// SetMetacConfigPath sets the config path +func SetMetacConfigPath(path string) ConfigMetaControllerOption { return func(c *ConfigMetaController) error { c.ConfigPath = path return nil @@ -134,9 +153,12 @@ func NewConfigMetaController( ) (*ConfigMetaController, error) { // initialize with defaults & the provided values ctl := &ConfigMetaController{ - WaitTimeoutForCondition: 30 * time.Minute, - WaitIntervalForCondition: 1 * time.Second, - opts: opts, + // Default setting for retry + // - Retry times out in 30 minutes + WaitTimeoutForStartAttempt: 30 * time.Minute, + // - Interval between retries is 1 second + WaitIntervalBetweenRestarts: 1 * time.Second, + opts: opts, BaseMetaController: BaseMetaController{ ResourceManager: resourceMgr, DynClientset: dynClientset, @@ -230,24 +252,27 @@ func (mc *ConfigMetaController) Start() { glog.Infof("Starting %s", mc) - // we run this as a continuous process - // until all the configs are loaded - err := mc.wait(mc.startAllWatchControllers) + // Run this with retries until all the configs are loaded + // and started. In other words, this starts all the + // generic controllers configured in config file eventually. + err := mc.startWithRetries(mc.startAllWatchControllers) if err != nil { glog.Fatalf("Failed to start %s: %+v", mc, err) } }() } -// wait polls the condition until it's true, with a configured -// interval and timeout. +// startWithRetries polls the condition until it's true, with +// a configured interval and timeout. // // The condition function returns a bool indicating whether it // is satisfied, as well as an error which should be non-nil if // and only if the function was unable to determine whether or // not the condition is satisfied (for example if the check // involves calling a remote server and the request failed). -func (mc *ConfigMetaController) wait(condition func() (bool, error)) error { +func (mc *ConfigMetaController) startWithRetries( + condition func() (bool, error), +) error { // mark the start time start := time.Now() for { @@ -257,31 +282,38 @@ func (mc *ConfigMetaController) wait(condition func() (bool, error)) error { // returning nil implies the condition has completed return nil } - if time.Since(start) > mc.WaitTimeoutForCondition { - return errors.Wrapf( - err, - "Condition timed out after %s: %s", - mc.WaitTimeoutForCondition, - mc, - ) + if time.Since(start) > mc.WaitTimeoutForStartAttempt && + (mc.RetryIndefinitelyUntilSucceed == nil || + !*mc.RetryIndefinitelyUntilSucceed) { + { + return errors.Errorf( + "Condition timed out after %s: %+v: %s", + mc.WaitTimeoutForStartAttempt, + err, + mc, + ) + } } if err != nil { - // Log error, but keep trying until timeout. + // condition resulted in error + // keep trying until timeout glog.V(7).Infof( - "Condition failed: Will retry after %s: %s: %v", - mc.WaitIntervalForCondition, - mc, + "Condition failed: Will retry after %s: %+v: %s", + mc.WaitIntervalBetweenRestarts, err, + mc, ) } else { + // condition did not pass + // keep trying until timeout glog.V(7).Infof( "Waiting for condition to succeed: Will retry after %s: %s", - mc.WaitIntervalForCondition, + mc.WaitIntervalBetweenRestarts, mc, ) } // wait & then continue retrying - time.Sleep(mc.WaitIntervalForCondition) + time.Sleep(mc.WaitIntervalBetweenRestarts) } } @@ -290,11 +322,12 @@ func (mc *ConfigMetaController) wait(condition func() (bool, error)) error { // binary // // NOTE: -// This method is used as a condition and hence can be invoked -// more than once. +// This method is used as a condition and is repeatedly executed +// under a loop till this condition is not met. func (mc *ConfigMetaController) startAllWatchControllers() (bool, error) { - // In this metacontroller, we are only responsible for - // starting/stopping the relevant watch based controllers + var errs []string + // This logic is responsible to start all the generic controllers + // configured in the config file for _, conf := range mc.Configs { key := conf.AsNamespaceNameKey() if _, ok := mc.WatchControllers[key]; ok { @@ -302,8 +335,7 @@ func (mc *ConfigMetaController) startAllWatchControllers() (bool, error) { // checks continue } - // watch controller i.e. a controller based on the resource - // specified in the **watch field** of GenericController + // Initialize the GenericController wc, err := NewWatchController( mc.ResourceManager, mc.DynClientset, @@ -311,17 +343,35 @@ func (mc *ConfigMetaController) startAllWatchControllers() (bool, error) { conf, ) if err != nil { - return false, errors.Wrapf( - err, - "Failed to init %s: %s", - key, - mc, + errs = append( + errs, + fmt.Sprintf( + "Failed to init gctl %s: %s", + key, + err.Error(), + ), ) + // continue to initialise & start remaining controllers + // + // NOTE: + // This helps operating controllers independently + // from other controllers that are currently experiencing + // issues. Most of the times these issues are temporary + // in nature. + continue } - // start this watch controller + // start this controller wc.Start(mc.WorkerCount) mc.WatchControllers[key] = wc } + if len(errs) != 0 { + return false, errors.Errorf( + "Failed to start all gctl controllers: %d errors found: %s: %s", + len(errs), + strings.Join(errs, ": "), + mc, + ) + } return true, nil } diff --git a/controller/generic/metacontroller_test.go b/controller/generic/metacontroller_test.go index aae3e55..5117ee3 100644 --- a/controller/generic/metacontroller_test.go +++ b/controller/generic/metacontroller_test.go @@ -159,7 +159,7 @@ func TestConfigMetaControllerIsDuplicateConfig(t *testing.T) { } } -func TestConfigMetaControllerWait(t *testing.T) { +func TestConfigMetaControllerStartWithRetry(t *testing.T) { var tests = map[string]struct { controller *ConfigMetaController condition func() (bool, error) @@ -167,8 +167,8 @@ func TestConfigMetaControllerWait(t *testing.T) { }{ "cond returns error": { controller: &ConfigMetaController{ - WaitIntervalForCondition: 1 * time.Second, - WaitTimeoutForCondition: 5 * time.Second, + WaitIntervalBetweenRestarts: 1 * time.Second, + WaitTimeoutForStartAttempt: 5 * time.Second, }, condition: func() (bool, error) { return false, errors.Errorf("Err") @@ -177,8 +177,8 @@ func TestConfigMetaControllerWait(t *testing.T) { }, "cond returns true": { controller: &ConfigMetaController{ - WaitIntervalForCondition: 1 * time.Second, - WaitTimeoutForCondition: 5 * time.Second, + WaitIntervalBetweenRestarts: 1 * time.Second, + WaitTimeoutForStartAttempt: 5 * time.Second, }, condition: func() (bool, error) { return true, nil @@ -187,13 +187,13 @@ func TestConfigMetaControllerWait(t *testing.T) { }, "cond returns false": { controller: &ConfigMetaController{ - WaitIntervalForCondition: 1 * time.Second, - WaitTimeoutForCondition: 5 * time.Second, + WaitIntervalBetweenRestarts: 1 * time.Second, + WaitTimeoutForStartAttempt: 5 * time.Second, }, condition: func() (bool, error) { return false, nil }, - isErr: false, + isErr: true, }, } for name, mock := range tests { @@ -201,7 +201,7 @@ func TestConfigMetaControllerWait(t *testing.T) { mock := mock t.Run(name, func(t *testing.T) { ctl := mock.controller - err := ctl.wait(mock.condition) + err := ctl.startWithRetries(mock.condition) if mock.isErr && err == nil { t.Fatalf("Expected error got none") } diff --git a/go.mod b/go.mod index 4727512..8949b48 100644 --- a/go.mod +++ b/go.mod @@ -6,7 +6,6 @@ go 1.13 require ( contrib.go.opencensus.io/exporter/prometheus v0.1.0 - github.com/coreos/etcd v3.3.15+incompatible // indirect github.com/evanphx/json-patch v4.5.0+incompatible // indirect github.com/ghodss/yaml v1.0.0 github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b diff --git a/server/server.go b/server/server.go index 204f076..822f9f7 100644 --- a/server/server.go +++ b/server/server.go @@ -240,6 +240,10 @@ type ConfigServer struct { // ConfigPath has higher priority GenericControllerConfigLoadFn func() ([]*v1alpha1.GenericController, error) + // This will allow executing start logic to be retried + // indefinitely till all the watch controllers are started + RetryIndefinitelyForStart *bool + // Number of workers per watch controller workerCount int } @@ -273,10 +277,9 @@ func (s *ConfigServer) Start(workerCount int) (stop func(), err error) { // various generic meta controller options to setup meta controller configOpts := []generic.ConfigMetaControllerOption{ - generic.SetMetaControllerConfigLoadFn( - s.GenericControllerConfigLoadFn, - ), - generic.SetMetaControllerConfigPath(s.ConfigPath), + generic.SetMetacConfigLoadFn(s.GenericControllerConfigLoadFn), + generic.SetMetacConfigPath(s.ConfigPath), + generic.SetMetacConfigToRetryIndefinitelyForStart(s.RetryIndefinitelyForStart), } genericMetac, err := generic.NewConfigMetaController( diff --git a/start/start.go b/start/start.go index 3f52e77..ca220e3 100644 --- a/start/start.go +++ b/start/start.go @@ -88,7 +88,13 @@ var ( "metac-config-path", "/etc/config/metac/", `Path to metac config file to let metac run as a self contained binary. - Needs run-as-local set to true`, + Applicable if run-as-local is set to true`, + ) + retryIndefinitelyToStart = flag.Bool( + "retry-indefinitely-to-start", + false, + `When true will let metac to retry continuously till all its controllers are started. + Applicable if run-as-local is set to true`, ) ) @@ -145,8 +151,9 @@ func Start() { // looking up various MetaController resources as // config files configServer := &server.ConfigServer{ - Server: mserver, - ConfigPath: *metacConfigPath, + Server: mserver, + ConfigPath: *metacConfigPath, + RetryIndefinitelyForStart: retryIndefinitelyToStart, } stopServer, err = configServer.Start(*workerCount) } else { diff --git a/test/integration/config-mode/set_status_on_cr_that_exists_later_test.go b/test/integration/config-mode/set_status_on_cr_that_exists_later_test.go new file mode 100644 index 0000000..2769503 --- /dev/null +++ b/test/integration/config-mode/set_status_on_cr_that_exists_later_test.go @@ -0,0 +1,201 @@ +/* +Copyright 2019 The MayaData 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 + + https://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 configmode + +import ( + "testing" + "time" + + "github.com/pkg/errors" + v1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" + "k8s.io/klog" + + "openebs.io/metac/apis/metacontroller/v1alpha1" + "openebs.io/metac/controller/generic" + "openebs.io/metac/server" + "openebs.io/metac/test/integration/framework" + k8s "openebs.io/metac/third_party/kubernetes" +) + +// TestSetStatusOnCRThatExistsLater will verify if GenericController can be +// used to implement setting of status against the watched +// resource +func TestSetStatusOnCRThatExistsLater(t *testing.T) { + if testing.Short() { + t.Skip("Skipping test in short mode.") + } + // name of the GenericController + ctlName := "lgctl-ssoctel" + + // name of the target namespace + targetNamespaceName := "ns-ssoctel" + + // name of the target resource + targetResName := "my-cr" + + f := framework.NewFixture(t) + defer f.TearDown() + + // ------------------------------------------------------------ + // Define the "reconcile logic" for sync i.e. create/update event + // ------------------------------------------------------------ + // + // NOTE: + // This makes use of inline function as hook + sHook := func(req *generic.SyncHookRequest, resp *generic.SyncHookResponse) error { + if resp == nil { + resp = &generic.SyncHookResponse{} + } + resp.Status = map[string]interface{}{ + "phase": "Active", + } + // there are no attachments to be reconciled + resp.SkipReconcile = true + return nil + } + + // Add this sync hook implementation to inline hook registry + var inlineHookName = "test/gctl-set-status-on-cr-that-exists-later" + generic.AddToInlineRegistry(inlineHookName, sHook) + + // --------------------------------------------------------- + // Define & Apply a GenericController i.e. a Meta Controller + // --------------------------------------------------------- + + // This is one of the meta controller that is defined as + // a Kubernetes custom resource. It listens to the resource + // specified in the watch field and acts against the resources + // specified in the attachments field. + gctlConfig := f.CreateGenericControllerAsMetacConfig( + ctlName, + + // set sync hook + generic.WithInlinehookSyncFunc(k8s.StringPtr(inlineHookName)), + + // custom resource is the watched resource + generic.WithWatch( + &v1alpha1.GenericControllerResource{ + ResourceRule: v1alpha1.ResourceRule{ + APIVersion: "test.metac.openebs.io/v1", + Resource: "crthatexistslaters", + }, + // We are interested only for our custom resource + NameSelector: []string{targetResName}, + }, + ), + ) + + // start metac that uses above GenericController instance as a config + var mserver = &server.Server{ + Config: framework.APIServerConfig, + DiscoveryInterval: 500 * time.Millisecond, + InformerRelist: 30 * time.Minute, + } + metacServer := &server.ConfigServer{ + Server: mserver, + GenericControllerConfigLoadFn: func() ([]*v1alpha1.GenericController, error) { + return []*v1alpha1.GenericController{gctlConfig}, nil + }, + RetryIndefinitelyForStart: k8s.BoolPtr(true), // target under test + } + stopMetac, err := metacServer.Start(5) + if err != nil { + t.Fatal(err) + } + defer stopMetac() + + // we wait for more than a minute & then create the CRD & CR + time.Sleep(1 * time.Minute) + + // --------------------------------------------------- + // Create the target namespace + // --------------------------------------------------- + // + // NOTE: + // Targeted CustomResources will be set in this namespace + targetNamespace, nsCreateErr := f.GetTypedClientset(). + CoreV1(). + Namespaces(). + Create( + &v1.Namespace{ + ObjectMeta: metav1.ObjectMeta{ + Name: targetNamespaceName, + }, + }, + ) + if nsCreateErr != nil { + t.Fatal(nsCreateErr) + } + + // ------------------------------------------------------ + // Create target CRD & CR to trigger above generic controller + // ------------------------------------------------------ + // + // Create a namespace scoped CoolNerd CRD & CR with finalizers + _, crClient, _ := f.SetupNamespaceCRDAndItsCR( + "CRThatExistsLater", + targetNamespace.GetName(), + targetResName, + ) + + // Need to wait & see if our controller works as expected + klog.Infof("Wait to verify CRThatExistsLater status") + + err = f.Wait(func() (bool, error) { + // ------------------------------------------- + // verify if custom resource is set with status + // ------------------------------------------- + crObj, err := crClient. + Namespace(targetNamespaceName). + Get( + targetResName, + metav1.GetOptions{}, + ) + if err != nil { + return false, errors.Wrapf( + err, + "Failed to get CRThatExistsLater %s", + targetResName, + ) + + } + // verify phase + phase, _, _ := unstructured.NestedString( + crObj.UnstructuredContent(), + "status", + "phase", + ) + if phase != "Active" { + return false, errors.Errorf( + "CRThatExistsLater %s status is not 'Active'", + targetResName, + ) + } + // condition passed + return true, nil + }) + + if err != nil { + t.Fatalf( + "Failed to set CRThatExistsLater status: %v", + err, + ) + } + klog.Infof("CRThatExistsLater status was set successfully") +} diff --git a/test/integration/framework/apply.go b/test/integration/framework/apply.go index d561faa..1d44dc2 100644 --- a/test/integration/framework/apply.go +++ b/test/integration/framework/apply.go @@ -147,7 +147,7 @@ func (a *Applyable) postCreateCRD( // discover custom resource API err := a.Retry.Waitf( func() (bool, error) { - got := apiDiscovery.GetAPIForAPIVersionAndResource( + got := APIDiscovery.GetAPIForAPIVersionAndResource( crd.Spec.Group+"/"+crd.Spec.Version, crd.Spec.Names.Plural, ) diff --git a/test/integration/framework/crd.go b/test/integration/framework/crd.go index bcec21c..8eacafa 100644 --- a/test/integration/framework/crd.go +++ b/test/integration/framework/crd.go @@ -116,7 +116,7 @@ func (f *Fixture) SetupCRD( klog.V(2).Infof("Discovering %s API", kind) err = f.Wait(func() (bool, error) { - return apiDiscovery.GetAPIForAPIVersionAndResource( + return APIDiscovery.GetAPIForAPIVersionAndResource( APIVersion, plural, ) != nil, nil diff --git a/test/integration/framework/fixture.go b/test/integration/framework/fixture.go index cdc1b4f..278a079 100644 --- a/test/integration/framework/fixture.go +++ b/test/integration/framework/fixture.go @@ -68,26 +68,26 @@ type Fixture struct { // NewFixture returns a new instance of Fixture func NewFixture(t *testing.T) *Fixture { crdClient, err := apiextensionsclientset.NewForConfig( - apiServerConfig, + APIServerConfig, ) if err != nil { t.Fatal(err) } dynamicClientset, err := dynamicclientset.New( - apiServerConfig, - apiDiscovery, + APIServerConfig, + APIDiscovery, ) if err != nil { t.Fatal(err) } metaClientset, err := metaclientset.NewForConfig( - apiServerConfig, + APIServerConfig, ) if err != nil { t.Fatal(err) } typedClientset, err := kubernetes.NewForConfig( - apiServerConfig, + APIServerConfig, ) if err != nil { t.Fatal(err) diff --git a/test/integration/framework/metacontroller.go b/test/integration/framework/metacontroller.go index ebcc823..1ef6957 100644 --- a/test/integration/framework/metacontroller.go +++ b/test/integration/framework/metacontroller.go @@ -220,7 +220,7 @@ func (f *Fixture) StartMetacFromGenericControllerConfig( gctlAsConfigFn func() ([]*v1alpha1.GenericController, error), ) (stop func()) { var mserver = &server.Server{ - Config: apiServerConfig, + Config: APIServerConfig, DiscoveryInterval: 500 * time.Millisecond, InformerRelist: 30 * time.Minute, } diff --git a/test/integration/framework/start.go b/test/integration/framework/start.go index 50d8c3d..b0b1661 100644 --- a/test/integration/framework/start.go +++ b/test/integration/framework/start.go @@ -33,8 +33,8 @@ import ( // These global variables are used in test functions to // invoke various kubernetes APIs -var apiDiscovery *dynamicdiscovery.APIResourceDiscovery -var apiServerConfig *rest.Config +var APIDiscovery *dynamicdiscovery.APIResourceDiscovery +var APIServerConfig *rest.Config // manifestDir is the path from the integration test binary // working dir to the directory containing metac manifests. @@ -104,24 +104,24 @@ func StartCRDBasedMetacBinary(testFns func() int) error { // set the config to this global variable which is in turn // used by the test functions - apiServerConfig, err = cp.GetRESTClientConfig() + APIServerConfig, err = cp.GetRESTClientConfig() if err != nil { return err } discoveryClient := discovery.NewDiscoveryClientForConfigOrDie( - apiServerConfig, + APIServerConfig, ) // set api resource discovery to this global variable which // is in turn used by the test functions - apiDiscovery = dynamicdiscovery.NewAPIResourceDiscoverer( + APIDiscovery = dynamicdiscovery.NewAPIResourceDiscoverer( discoveryClient, ) // We don't care about stopping this cleanly since it has no // external effects. - apiDiscovery.Start(500 * time.Millisecond) + APIDiscovery.Start(500 * time.Millisecond) // Run the actual tests now since setup is up & running if exitCode := testFns(); exitCode != 0 { @@ -168,7 +168,7 @@ func StartCRDBasedMetacServer(testFns func() int) error { // set the config to this global variable which // is in turn used by the test functions - apiServerConfig, err = cp.GetRESTClientConfig() + APIServerConfig, err = cp.GetRESTClientConfig() if err != nil { return err } @@ -180,7 +180,7 @@ func StartCRDBasedMetacServer(testFns func() int) error { // code under test. metac := &server.CRDServer{ Server: &server.Server{ - Config: apiServerConfig, + Config: APIServerConfig, DiscoveryInterval: 500 * time.Millisecond, InformerRelist: 30 * time.Minute, }, @@ -198,18 +198,18 @@ func StartCRDBasedMetacServer(testFns func() int) error { klog.V(2).Info("Started CRD based metac server") discoveryClient := discovery.NewDiscoveryClientForConfigOrDie( - apiServerConfig, + APIServerConfig, ) // set api resource discovery to this global variable which // is in turn used by the test functions - apiDiscovery = dynamicdiscovery.NewAPIResourceDiscoverer( + APIDiscovery = dynamicdiscovery.NewAPIResourceDiscoverer( discoveryClient, ) // We don't care about stopping this cleanly since it has no // external effects. - apiDiscovery.Start(500 * time.Millisecond) + APIDiscovery.Start(500 * time.Millisecond) // Run the actual tests now since setup is up & running // successfully @@ -245,24 +245,24 @@ func StartConfigBasedMetacServer(testFns func() int) error { // set the config to this global variable which // is in turn used by the test functions - apiServerConfig, err = cp.GetRESTClientConfig() + APIServerConfig, err = cp.GetRESTClientConfig() if err != nil { return err } discoveryClient := discovery.NewDiscoveryClientForConfigOrDie( - apiServerConfig, + APIServerConfig, ) // set api resource discovery to this global variable which // is in turn used by the test functions - apiDiscovery = dynamicdiscovery.NewAPIResourceDiscoverer( + APIDiscovery = dynamicdiscovery.NewAPIResourceDiscoverer( discoveryClient, ) // We don't care about stopping this cleanly since it has no // external effects. - apiDiscovery.Start(500 * time.Millisecond) + APIDiscovery.Start(500 * time.Millisecond) // Run the actual tests now since setup is up & running // successfully