From 1cace8cd1443a2b6cd7685ee30bc32e5b1b86b41 Mon Sep 17 00:00:00 2001 From: "Adam D. Cornett" Date: Tue, 1 Oct 2024 09:53:57 -0700 Subject: [PATCH] adding a flag for subscription timeout for check operator cmd Signed-off-by: Adam D. Cornett --- cmd/preflight/cmd/check_operator.go | 9 +++++++++ cmd/preflight/cmd/root.go | 3 +++ internal/engine/engine.go | 3 ++- internal/policy/operator/default.go | 4 ---- internal/policy/operator/deployable_by_olm.go | 20 +++++++++++++------ .../policy/operator/deployable_by_olm_test.go | 5 +---- internal/runtime/config.go | 18 +++++++++-------- internal/runtime/config_test.go | 6 ++++-- internal/runtime/defaults.go | 5 ++++- operator/check_operator.go | 18 +++++++++++++---- 10 files changed, 61 insertions(+), 30 deletions(-) diff --git a/cmd/preflight/cmd/check_operator.go b/cmd/preflight/cmd/check_operator.go index 2919bd7a..bbd0bb67 100644 --- a/cmd/preflight/cmd/check_operator.go +++ b/cmd/preflight/cmd/check_operator.go @@ -56,7 +56,12 @@ func checkOperatorCmd(runpreflight runPreflight) *cobra.Command { "If empty the default of 180s will be used. (env: PFLT_CSV_TIMEOUT)") _ = viper.BindPFlag("csv_timeout", checkOperatorCmd.Flags().Lookup("csv-timeout")) + checkOperatorCmd.Flags().Duration("subscription-timeout", 0, "The Duration of time to wait for the Subscription to become healthy.\n"+ + "If empty the default of 180s will be used. (env: PFLT_SUBSCRIPTION_TIMEOUT)") + _ = viper.BindPFlag("subscription_timeout", checkOperatorCmd.Flags().Lookup("subscription-timeout")) + _ = checkOperatorCmd.Flags().MarkHidden("csv-timeout") + _ = checkOperatorCmd.Flags().MarkHidden("subscription-timeout") return checkOperatorCmd } @@ -179,6 +184,10 @@ func generateOperatorCheckOptions(cfg *runtime.Config) []operator.Option { opts = append(opts, operator.WithCSVTimeout(cfg.CSVTimeout)) } + if cfg.SubscriptionTimeout != 0 { + opts = append(opts, operator.WithSubscriptionTimeout(cfg.SubscriptionTimeout)) + } + return opts } diff --git a/cmd/preflight/cmd/root.go b/cmd/preflight/cmd/root.go index ec3419c7..a8a464de 100644 --- a/cmd/preflight/cmd/root.go +++ b/cmd/preflight/cmd/root.go @@ -92,6 +92,9 @@ func initConfig(viper *spfviper.Viper) { // Set up csv timout default viper.SetDefault("csv_timeout", runtime.DefaultCSVTimeout) + + // Set up subscription timeout default + viper.SetDefault("subscription_timeout", runtime.DefaultSubscriptionTimeout) } // preRunConfig is used by cobra.PreRun in all non-root commands to load all necessary configurations diff --git a/internal/engine/engine.go b/internal/engine/engine.go index ad278d16..76e81ea2 100644 --- a/internal/engine/engine.go +++ b/internal/engine/engine.go @@ -723,6 +723,7 @@ type OperatorCheckConfig struct { IndexImage, DockerConfig, Channel string Kubeconfig []byte CSVTimeout time.Duration + SubscriptionTimeout time.Duration } // InitializeOperatorChecks returns opeartor checks for policy p give cfg. @@ -732,7 +733,7 @@ func InitializeOperatorChecks(ctx context.Context, p policy.Policy, cfg Operator return []check.Check{ operatorpol.NewScorecardBasicSpecCheck(operatorsdk.New(cfg.ScorecardImage, exec.Command), cfg.ScorecardNamespace, cfg.ScorecardServiceAccount, cfg.Kubeconfig, cfg.ScorecardWaitTime), operatorpol.NewScorecardOlmSuiteCheck(operatorsdk.New(cfg.ScorecardImage, exec.Command), cfg.ScorecardNamespace, cfg.ScorecardServiceAccount, cfg.Kubeconfig, cfg.ScorecardWaitTime), - operatorpol.NewDeployableByOlmCheck(cfg.IndexImage, cfg.DockerConfig, cfg.Channel, operatorpol.WithCSVTimeout(cfg.CSVTimeout)), + operatorpol.NewDeployableByOlmCheck(cfg.IndexImage, cfg.DockerConfig, cfg.Channel, operatorpol.WithCSVTimeout(cfg.CSVTimeout), operatorpol.WithSubscriptionTimeout(cfg.SubscriptionTimeout)), operatorpol.NewValidateOperatorBundleCheck(), operatorpol.NewCertifiedImagesCheck(pyxis.NewPyxisClient( check.DefaultPyxisHost, diff --git a/internal/policy/operator/default.go b/internal/policy/operator/default.go index 096caaa4..afd56a76 100644 --- a/internal/policy/operator/default.go +++ b/internal/policy/operator/default.go @@ -1,8 +1,6 @@ package operator import ( - "time" - operatorsv1alpha1 "github.com/operator-framework/api/pkg/operators/v1alpha1" ) @@ -30,8 +28,6 @@ const ( ) var ( - subscriptionTimeout time.Duration = 180 * time.Second - approvedRegistries = map[string]struct{}{ "registry.connect.dev.redhat.com": {}, "registry.connect.qa.redhat.com": {}, diff --git a/internal/policy/operator/deployable_by_olm.go b/internal/policy/operator/deployable_by_olm.go index 673ee769..53e2b70e 100644 --- a/internal/policy/operator/deployable_by_olm.go +++ b/internal/policy/operator/deployable_by_olm.go @@ -57,11 +57,12 @@ type DeployableByOlmCheck struct { // channel is optional. If empty, we will introspect. channel string - openshiftClient openshift.Client - client crclient.Client - csvReady bool - validImages bool - csvTimeout time.Duration + openshiftClient openshift.Client + client crclient.Client + csvReady bool + validImages bool + csvTimeout time.Duration + subscriptionTimeout time.Duration } func (p *DeployableByOlmCheck) initClient() error { @@ -106,6 +107,13 @@ func WithCSVTimeout(csvTimeout time.Duration) Option { } } +// WithSubscriptionTimeout customizes how long to wait for a subscription to become healthy. +func WithSubscriptionTimeout(subscriptionTimeout time.Duration) Option { + return func(oc *DeployableByOlmCheck) { + oc.subscriptionTimeout = subscriptionTimeout + } +} + // NewDeployableByOlmCheck will return a check that validates if an operator // is deployable by OLM. An empty dockerConfig value implies that the images // in scope are public. An empty channel value implies that the check should @@ -549,7 +557,7 @@ func (p *DeployableByOlmCheck) installedCSV(ctx context.Context, operatorData op var wg sync.WaitGroup // query API server for the installed CSV field of the created subscription wg.Add(1) - go watch(ctx, p.openshiftClient, &wg, operatorData.App, operatorData.InstallNamespace, subscriptionTimeout, installedCSVChannel, subscriptionCsvIsInstalled) + go watch(ctx, p.openshiftClient, &wg, operatorData.App, operatorData.InstallNamespace, p.subscriptionTimeout, installedCSVChannel, subscriptionCsvIsInstalled) go func() { wg.Wait() diff --git a/internal/policy/operator/deployable_by_olm_test.go b/internal/policy/operator/deployable_by_olm_test.go index f9376800..2dcd8450 100644 --- a/internal/policy/operator/deployable_by_olm_test.go +++ b/internal/policy/operator/deployable_by_olm_test.go @@ -27,16 +27,13 @@ var _ = Describe("DeployableByOLMCheck", func() { ) BeforeEach(func() { - // override default timeout - subscriptionTimeout = 1 * time.Second - fakeImage := fakecranev1.FakeImage{} imageRef.ImageInfo = &fakeImage imageRef.ImageFSPath = "./testdata/all_namespaces" now := metav1.Now() og.Status.LastUpdated = &now - deployableByOLMCheck = *NewDeployableByOlmCheck("test_indeximage", "", "", WithCSVTimeout(1*time.Second)) + deployableByOLMCheck = *NewDeployableByOlmCheck("test_indeximage", "", "", WithCSVTimeout(1*time.Second), WithSubscriptionTimeout(1*time.Second)) scheme := apiruntime.NewScheme() Expect(openshift.AddSchemes(scheme)).To(Succeed()) clientBuilder = fake.NewClientBuilder(). diff --git a/internal/runtime/config.go b/internal/runtime/config.go index fdcd8ea3..c07326b1 100644 --- a/internal/runtime/config.go +++ b/internal/runtime/config.go @@ -31,14 +31,15 @@ type Config struct { Offline bool ManifestListDigest string // Operator-Specific Fields - Namespace string - ServiceAccount string - ScorecardImage string - ScorecardWaitTime string - Channel string - IndexImage string - Kubeconfig string - CSVTimeout time.Duration + Namespace string + ServiceAccount string + ScorecardImage string + ScorecardWaitTime string + Channel string + IndexImage string + Kubeconfig string + CSVTimeout time.Duration + SubscriptionTimeout time.Duration } // ReadOnly returns an uneditably configuration. @@ -86,6 +87,7 @@ func (c *Config) storeOperatorPolicyConfiguration(vcfg viper.Viper) { c.Channel = vcfg.GetString("channel") c.IndexImage = vcfg.GetString("indeximage") c.CSVTimeout = vcfg.GetDuration("csv_timeout") + c.SubscriptionTimeout = vcfg.GetDuration("subscription_timeout") } // This is to satisfy the CraneConfig interface diff --git a/internal/runtime/config_test.go b/internal/runtime/config_test.go index 225ca07b..e2ce0aba 100644 --- a/internal/runtime/config_test.go +++ b/internal/runtime/config_test.go @@ -56,6 +56,8 @@ var _ = Describe("Viper to Runtime Config", func() { expectedRuntimeCfg.IndexImage = "myindeximage" baseViperCfg.Set("csv_timeout", DefaultCSVTimeout) expectedRuntimeCfg.CSVTimeout = DefaultCSVTimeout + baseViperCfg.Set("subscription_timeout", DefaultSubscriptionTimeout) + expectedRuntimeCfg.SubscriptionTimeout = DefaultSubscriptionTimeout }) Context("With values in a viper config", func() { @@ -66,12 +68,12 @@ var _ = Describe("Viper to Runtime Config", func() { }) }) - It("should only have 25 struct keys for tests to be valid", func() { + It("should only have 26 struct keys for tests to be valid", func() { // If this test fails, it means a developer has added or removed // keys from runtime.Config, and so these tests may no longer be // accurate in confirming that the derived configuration from viper // matches. keys := reflect.TypeOf(Config{}).NumField() - Expect(keys).To(Equal(25)) + Expect(keys).To(Equal(26)) }) }) diff --git a/internal/runtime/defaults.go b/internal/runtime/defaults.go index e24fede3..ff0ab629 100644 --- a/internal/runtime/defaults.go +++ b/internal/runtime/defaults.go @@ -2,4 +2,7 @@ package runtime import "time" -var DefaultCSVTimeout = 180 * time.Second +var ( + DefaultCSVTimeout = 180 * time.Second + DefaultSubscriptionTimeout = 180 * time.Second +) diff --git a/operator/check_operator.go b/operator/check_operator.go index ca6665dd..4c491f06 100644 --- a/operator/check_operator.go +++ b/operator/check_operator.go @@ -22,10 +22,11 @@ const defaultScorecardWaitTime = "240" // NewCheck is a check runner that executes the Operator Policy. func NewCheck(image, indeximage string, kubeconfig []byte, opts ...Option) *operatorCheck { c := &operatorCheck{ - image: image, - kubeconfig: kubeconfig, - indeximage: indeximage, - scorecardWaitTime: defaultScorecardWaitTime, + image: image, + kubeconfig: kubeconfig, + indeximage: indeximage, + scorecardWaitTime: defaultScorecardWaitTime, + subscriptionTimeout: runtime.DefaultSubscriptionTimeout, } for _, opt := range opts { @@ -94,6 +95,7 @@ func (c *operatorCheck) resolve(ctx context.Context) error { Channel: c.operatorChannel, Kubeconfig: c.kubeconfig, CSVTimeout: c.csvTimeout, + SubscriptionTimeout: c.subscriptionTimeout, }) if err != nil { return fmt.Errorf("%w: %s", preflighterr.ErrCannotInitializeChecks, err) @@ -174,6 +176,13 @@ func WithCSVTimeout(csvTimeout time.Duration) Option { } } +// WithSubscriptionTimeout customizes how long to wait for a subscription to become healthy. +func WithSubscriptionTimeout(subscriptionTimeout time.Duration) Option { + return func(oc *operatorCheck) { + oc.subscriptionTimeout = subscriptionTimeout + } +} + type operatorCheck struct { // required image string @@ -191,4 +200,5 @@ type operatorCheck struct { resolved bool policy policy.Policy csvTimeout time.Duration + subscriptionTimeout time.Duration }