From f28da4210cd1eaeb4a1ac07d93d4a378fd2c18bd Mon Sep 17 00:00:00 2001 From: Matt Butcher Date: Tue, 3 Sep 2019 12:37:09 -0600 Subject: [PATCH] fix: wait for CRD to register before allowing CRDs to be installed This fixes an issue with the previous version of this patch in which the CRD would not be available quickly enough. Signed-off-by: Matt Butcher --- pkg/action/install.go | 78 +++++++++++++++++++++++-------------------- 1 file changed, 42 insertions(+), 36 deletions(-) diff --git a/pkg/action/install.go b/pkg/action/install.go index 6efcdf22e..6c56f2ba4 100644 --- a/pkg/action/install.go +++ b/pkg/action/install.go @@ -111,41 +111,9 @@ func (i *Install) Run(chrt *chart.Chart, vals map[string]interface{}) (*release. return nil, err } - if i.ClientOnly { - // Add mock objects in here so it doesn't use Kube API server - // NOTE(bacongobbler): used for `helm template` - i.cfg.Capabilities = chartutil.DefaultCapabilities - i.cfg.KubeClient = &kubefake.PrintingKubeClient{Out: ioutil.Discard} - i.cfg.Releases = storage.Init(driver.NewMemory()) - } - - if err := chartutil.ProcessDependencies(chrt, vals); err != nil { - return nil, err - } - - // Make sure if Atomic is set, that wait is set as well. This makes it so - // the user doesn't have to specify both - i.Wait = i.Wait || i.Atomic - - caps, err := i.cfg.getCapabilities() - if err != nil { - return nil, err - } - - options := chartutil.ReleaseOptions{ - Name: i.ReleaseName, - Namespace: i.Namespace, - IsInstall: true, - } - valuesToRender, err := chartutil.ToRenderValues(chrt, vals, options, caps) - if err != nil { - return nil, err - } - - rel := i.createRelease(chrt, vals) - - // Pre-install anything in the crd/ directory - if crds := chrt.CRDs(); !i.SkipCRDs && len(crds) > 0 { + // Pre-install anything in the crd/ directory. We do this before Helm + // contacts the upstream server and builds the capabilities object. + if crds := chrt.CRDs(); !i.ClientOnly && !i.SkipCRDs && len(crds) > 0 { // We do these one at a time in the order they were read. for _, obj := range crds { // Read in the resources @@ -167,7 +135,7 @@ func (i *Install) Run(chrt *chart.Chart, vals map[string]interface{}) (*release. i.cfg.Log("CRD %s is already present. Skipping.", crdName) continue } - return i.failRelease(rel, err) + return nil, err } // Invalidate the local cache. @@ -176,11 +144,49 @@ func (i *Install) Run(chrt *chart.Chart, vals map[string]interface{}) (*release. // to impact the majority of charts. i.cfg.Log("Could not clear the discovery cache: %s", err) } else { + i.cfg.Log("Clearing discovery cache") discoveryClient.Invalidate() + // Give time for the CRD to be recognized. + time.Sleep(5 * time.Second) + // Make sure to force a rebuild of the cache. + discoveryClient.ServerGroups() } } } + if i.ClientOnly { + // Add mock objects in here so it doesn't use Kube API server + // NOTE(bacongobbler): used for `helm template` + i.cfg.Capabilities = chartutil.DefaultCapabilities + i.cfg.KubeClient = &kubefake.PrintingKubeClient{Out: ioutil.Discard} + i.cfg.Releases = storage.Init(driver.NewMemory()) + } + + if err := chartutil.ProcessDependencies(chrt, vals); err != nil { + return nil, err + } + + // Make sure if Atomic is set, that wait is set as well. This makes it so + // the user doesn't have to specify both + i.Wait = i.Wait || i.Atomic + + caps, err := i.cfg.getCapabilities() + if err != nil { + return nil, err + } + + options := chartutil.ReleaseOptions{ + Name: i.ReleaseName, + Namespace: i.Namespace, + IsInstall: true, + } + valuesToRender, err := chartutil.ToRenderValues(chrt, vals, options, caps) + if err != nil { + return nil, err + } + + rel := i.createRelease(chrt, vals) + var manifestDoc *bytes.Buffer rel.Hooks, manifestDoc, rel.Info.Notes, err = i.cfg.renderResources(chrt, valuesToRender, i.OutputDir) // Even for errors, attach this if available