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