From cd655cd98e15d321afe4a978cfcf527dce23a57b Mon Sep 17 00:00:00 2001 From: Nader Ziada Date: Tue, 31 Mar 2020 15:44:44 -0400 Subject: [PATCH] Make clusterctl cert-manager timeout configurable - cert-manager-timeout can be set in config file - default of 10 minutes if no value is set --- cmd/clusterctl/client/cluster/cert_manager.go | 22 +++- .../client/cluster/cert_manager_test.go | 110 ++++++++++++++++++ docs/book/src/clusterctl/configuration.md | 12 ++ 3 files changed, 141 insertions(+), 3 deletions(-) create mode 100644 cmd/clusterctl/client/cluster/cert_manager_test.go diff --git a/cmd/clusterctl/client/cluster/cert_manager.go b/cmd/clusterctl/client/cluster/cert_manager.go index 4f9b9b6ff9b5..61d56c75737b 100644 --- a/cmd/clusterctl/client/cluster/cert_manager.go +++ b/cmd/clusterctl/client/cluster/cert_manager.go @@ -33,10 +33,11 @@ import ( const ( embeddedCertManagerManifestPath = "cmd/clusterctl/config/manifest/cert-manager.yaml" - waitCertManagerInterval = 1 * time.Second - waitCertManagerTimeout = 10 * time.Minute + waitCertManagerInterval = 1 * time.Second + waitCertManagerDefaultTimeout = 10 * time.Minute certManagerImageComponent = "cert-manager" + timeoutConfigKey = "cert-manager-timeout" ) // CertManagerClient has methods to work with cert-manager components in the cluster. @@ -134,7 +135,7 @@ func (cm *certManagerClient) EnsureWebhook() error { // Waits for for the cert-manager web-hook to be available. log.Info("Waiting for cert-manager to be available...") - if err := cm.pollImmediateWaiter(waitCertManagerInterval, waitCertManagerTimeout, func() (bool, error) { + if err := cm.pollImmediateWaiter(waitCertManagerInterval, cm.getWaitTimeout(), func() (bool, error) { webhook, err := cm.getWebhook() if err != nil { //Nb. we are ignoring the error so the pollImmediateWaiter will execute another retry @@ -157,6 +158,21 @@ func (cm *certManagerClient) EnsureWebhook() error { return nil } +func (cm *certManagerClient) getWaitTimeout() time.Duration { + log := logf.Log + + timeout, err := cm.configClient.Variables().Get(timeoutConfigKey) + if err != nil { + return waitCertManagerDefaultTimeout + } + timeoutDuration, err := time.ParseDuration(timeout) + if err != nil { + log.Info("Invalid value set for ", timeoutConfigKey, timeout) + return waitCertManagerDefaultTimeout + } + return timeoutDuration +} + // getManifestObjs gets the cert-manager manifest, convert to unstructured objects, and fix images func (cm *certManagerClient) getManifestObjs() ([]unstructured.Unstructured, error) { yaml, err := manifests.Asset(embeddedCertManagerManifestPath) diff --git a/cmd/clusterctl/client/cluster/cert_manager_test.go b/cmd/clusterctl/client/cluster/cert_manager_test.go new file mode 100644 index 000000000000..d4657d88b453 --- /dev/null +++ b/cmd/clusterctl/client/cluster/cert_manager_test.go @@ -0,0 +1,110 @@ +/* +Copyright 2020 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package cluster + +import ( + "testing" + "time" + + . "github.com/onsi/gomega" + "k8s.io/apimachinery/pkg/util/wait" + "sigs.k8s.io/cluster-api/cmd/clusterctl/client/config" + "sigs.k8s.io/cluster-api/cmd/clusterctl/internal/test" +) + +func Test_GetTimeout(t *testing.T) { + + pollImmediateWaiter := func(interval, timeout time.Duration, condition wait.ConditionFunc) error { + return nil + } + + tests := []struct { + name string + timeout string + want time.Duration + }{ + { + name: "no custom value set for timeout", + timeout: "", + want: 10 * time.Minute, + }, + { + name: "a custom value of timeout is set", + timeout: "5m", + want: 5 * time.Minute, + }, + { + name: "invalid custom value of timeout is set", + timeout: "5", + want: 10 * time.Minute, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + g := NewWithT(t) + + fakeConfigClient := newFakeConfig(tt.timeout) + + cm := newCertMangerClient(fakeConfigClient, nil, pollImmediateWaiter) + tm := cm.getWaitTimeout() + + g.Expect(tm).To(Equal(tt.want)) + }) + } + +} + +func newFakeConfig(timeout string) fakeConfigClient { + fakeReader := test.NewFakeReader().WithVar("cert-manager-timeout", timeout) + + client, _ := config.New("fake-config", config.InjectReader(fakeReader)) + return fakeConfigClient{ + fakeReader: fakeReader, + internalclient: client, + certManagerTimeout: timeout, + } +} + +type fakeConfigClient struct { + fakeReader *test.FakeReader + internalclient config.Client + certManagerTimeout string +} + +var _ config.Client = &fakeConfigClient{} + +func (f fakeConfigClient) Providers() config.ProvidersClient { + return f.internalclient.Providers() +} + +func (f fakeConfigClient) Variables() config.VariablesClient { + return f.internalclient.Variables() +} + +func (f fakeConfigClient) ImageMeta() config.ImageMetaClient { + return f.internalclient.ImageMeta() +} + +func (f *fakeConfigClient) WithVar(key, value string) *fakeConfigClient { + f.fakeReader.WithVar(key, value) + return f +} + +func (f *fakeConfigClient) WithProvider(provider config.Provider) *fakeConfigClient { + f.fakeReader.WithProvider(provider.Name(), provider.Type(), provider.URL()) + return f +} diff --git a/docs/book/src/clusterctl/configuration.md b/docs/book/src/clusterctl/configuration.md index 8c640484c413..22e0101d786e 100644 --- a/docs/book/src/clusterctl/configuration.md +++ b/docs/book/src/clusterctl/configuration.md @@ -154,3 +154,15 @@ images: In this example we are overriding the image repository for all the components and the image tag for all the images in the cert-manager component. + +## Cert-Manager timeout override + +For situations when resources are limited or the network is slow, the cert-manager wait time to be running can be customized by adding a field to the clusterctl config file, for example: + +```yaml + cert-manager-timeout: 15m +``` + +The value string is a possibly signed sequence of decimal numbers, each with optional fraction and a unit suffix, such as "300ms", "-1.5h" or "2h45m". Valid time units are "ns", "us" (or "µs"), "ms", "s", "m", "h". + +If no value is specified or the format is invalid, the default value of 10 minutes will be used. \ No newline at end of file