Merge pull request #6243 from technosophos/feat/5871-crds-directory

feat: Add support for a crds/ directory
pull/6282/head
Matt Farina 5 years ago committed by GitHub
commit fba311ba23
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -131,6 +131,7 @@ func addInstallFlags(f *pflag.FlagSet, client *action.Install, valueOpts *values
f.BoolVar(&client.Devel, "devel", false, "use development versions, too. Equivalent to version '>0.0.0-0'. If --version is set, this is ignored.") f.BoolVar(&client.Devel, "devel", false, "use development versions, too. Equivalent to version '>0.0.0-0'. If --version is set, this is ignored.")
f.BoolVar(&client.DependencyUpdate, "dependency-update", false, "run helm dependency update before installing the chart") f.BoolVar(&client.DependencyUpdate, "dependency-update", false, "run helm dependency update before installing the chart")
f.BoolVar(&client.Atomic, "atomic", false, "if set, installation process purges chart on fail. The --wait flag will be set automatically if --atomic is used") f.BoolVar(&client.Atomic, "atomic", false, "if set, installation process purges chart on fail. The --wait flag will be set automatically if --atomic is used")
f.BoolVar(&client.SkipCRDs, "skip-crds", false, "if set, no CRDs will be installed. By default, CRDs are installed if not already present.")
addValueOptionsFlags(f, valueOpts) addValueOptionsFlags(f, valueOpts)
addChartPathOptionsFlags(f, &client.ChartPathOptions) addChartPathOptionsFlags(f, &client.ChartPathOptions)
} }

@ -29,6 +29,7 @@ import (
"github.com/Masterminds/sprig" "github.com/Masterminds/sprig"
"github.com/pkg/errors" "github.com/pkg/errors"
apierrors "k8s.io/apimachinery/pkg/api/errors"
"helm.sh/helm/pkg/chart" "helm.sh/helm/pkg/chart"
"helm.sh/helm/pkg/chartutil" "helm.sh/helm/pkg/chartutil"
@ -80,8 +81,10 @@ type Install struct {
NameTemplate string NameTemplate string
OutputDir string OutputDir string
Atomic bool Atomic bool
SkipCRDs bool
} }
// ChartPathOptions captures common options used for controlling chart paths
type ChartPathOptions struct { type ChartPathOptions struct {
CaFile string // --ca-file CaFile string // --ca-file
CertFile string // --cert-file CertFile string // --cert-file
@ -141,6 +144,35 @@ func (i *Install) Run(chrt *chart.Chart, vals map[string]interface{}) (*release.
} }
rel := i.createRelease(chrt, vals) rel := i.createRelease(chrt, vals)
// Pre-install anything in the crd/ directory
if crds := chrt.CRDs(); !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
res, err := i.cfg.KubeClient.Build(bytes.NewBuffer(obj.Data))
if err != nil {
// We bail out immediately
return nil, errors.Wrapf(err, "failed to install CRD %s", obj.Name)
}
// On dry run, bail here
if i.DryRun {
i.cfg.Log("WARNING: This chart or one of its subcharts contains CRDs. Rendering may fail or contain inaccuracies.")
continue
}
// Send them to Kube
if _, err := i.cfg.KubeClient.Create(res); err != nil {
// If the error is CRD already exists, continue.
if apierrors.IsAlreadyExists(err) {
crdName := res[0].Name
i.cfg.Log("CRD %s is already present. Skipping.", crdName)
continue
}
return i.failRelease(rel, err)
}
}
}
var manifestDoc *bytes.Buffer var manifestDoc *bytes.Buffer
rel.Hooks, manifestDoc, rel.Info.Notes, err = i.cfg.renderResources(chrt, valuesToRender, i.OutputDir) rel.Hooks, manifestDoc, rel.Info.Notes, err = i.cfg.renderResources(chrt, valuesToRender, i.OutputDir)
// Even for errors, attach this if available // Even for errors, attach this if available
@ -484,6 +516,7 @@ func (i *Install) NameAndChart(args []string) (string, string, error) {
return fmt.Sprintf("%s-%d", base, time.Now().Unix()), args[0], nil return fmt.Sprintf("%s-%d", base, time.Now().Unix()), args[0], nil
} }
// TemplateName renders a name template, returning the name or an error.
func TemplateName(nameTemplate string) (string, error) { func TemplateName(nameTemplate string) (string, error) {
if nameTemplate == "" { if nameTemplate == "" {
return "", nil return "", nil
@ -501,6 +534,7 @@ func TemplateName(nameTemplate string) (string, error) {
return b.String(), nil return b.String(), nil
} }
// CheckDependencies checks the dependencies for a chart.
func CheckDependencies(ch *chart.Chart, reqs []*chart.Dependency) error { func CheckDependencies(ch *chart.Chart, reqs []*chart.Dependency) error {
var missing []string var missing []string

@ -15,6 +15,8 @@ limitations under the License.
package chart package chart
import "strings"
// APIVersionV1 is the API version number for version 1. // APIVersionV1 is the API version number for version 1.
const APIVersionV1 = "v1" const APIVersionV1 = "v1"
@ -97,6 +99,7 @@ func (ch *Chart) ChartFullPath() string {
return ch.Name() return ch.Name()
} }
// Validate validates the metadata.
func (ch *Chart) Validate() error { func (ch *Chart) Validate() error {
return ch.Metadata.Validate() return ch.Metadata.Validate()
} }
@ -108,3 +111,19 @@ func (ch *Chart) AppVersion() string {
} }
return ch.Metadata.AppVersion return ch.Metadata.AppVersion
} }
// CRDs returns a list of File objects in the 'crds/' directory of a Helm chart.
func (ch *Chart) CRDs() []*File {
files := []*File{}
// Find all resources in the crds/ directory
for _, f := range ch.Files {
if strings.HasPrefix(f.Name, "crds/") {
files = append(files, f)
}
}
// Get CRDs from dependencies, too.
for _, dep := range ch.Dependencies() {
files = append(files, dep.CRDs()...)
}
return files
}

@ -0,0 +1,51 @@
/*
Copyright The Helm 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 chart
import (
"testing"
"github.com/stretchr/testify/assert"
)
func TestCRDs(t *testing.T) {
chrt := Chart{
Files: []*File{
{
Name: "crds/foo.yaml",
Data: []byte("hello"),
},
{
Name: "bar.yaml",
Data: []byte("hello"),
},
{
Name: "crds/foo/bar/baz.yaml",
Data: []byte("hello"),
},
{
Name: "crdsfoo/bar/baz.yaml",
Data: []byte("hello"),
},
},
}
is := assert.New(t)
crds := chrt.CRDs()
is.Equal(2, len(crds))
is.Equal("crds/foo.yaml", crds[0].Name)
is.Equal("crds/foo/bar/baz.yaml", crds[1].Name)
}

@ -64,6 +64,7 @@ type Metadata struct {
Type string `json:"type,omitempty"` Type string `json:"type,omitempty"`
} }
// Validate checks the metadata for known issues, returning an error if metadata is not correct
func (md *Metadata) Validate() error { func (md *Metadata) Validate() error {
if md == nil { if md == nil {
return ValidationError("chart.metadata is required") return ValidationError("chart.metadata is required")

Loading…
Cancel
Save