Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow defining a subset of subcharts to be updated when using CRD upgrader #51

Merged
merged 1 commit into from
Jun 21, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 17 additions & 3 deletions cmd/kubectl-k8ssandra/helm/crds.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ type options struct {
chartRepo string
repoURL string
download bool
chartList []string
}

func newOptions(streams genericclioptions.IOStreams) *options {
Expand All @@ -49,13 +50,17 @@ func NewUpgradeCmd(streams genericclioptions.IOStreams) *cobra.Command {
Short: "upgrade CRDs from chart to target version",
Example: fmt.Sprintf(upgraderExample, "kubectl k8ssandra helm crds"),
SilenceUsage: true,
RunE: func(c *cobra.Command, args []string) error {
PreRunE: func(c *cobra.Command, args []string) error {
if err := o.Complete(c, args); err != nil {
return err
}
if err := o.Validate(); err != nil {
return err
}

return nil
},
RunE: func(c *cobra.Command, args []string) error {
if err := o.Run(); err != nil {
log.Error("Error upgrading CustomResourceDefinitions", "error", err)
return err
Expand All @@ -70,16 +75,25 @@ func NewUpgradeCmd(streams genericclioptions.IOStreams) *cobra.Command {
fl.StringVar(&o.chartVersion, "chartVersion", "", "chartVersion to upgrade to")
fl.StringVar(&o.chartRepo, "chartRepo", "", "optional chart repository name to override the default (k8ssandra)")
fl.StringVar(&o.repoURL, "repoURL", "", "optional chart repository url to override the default (helm.k8ssandra.io)")
fl.StringSliceVar(&o.chartList, "charts", []string{}, "optional list of dependency charts to upgrade, default is just the main chart. Use \"_\" to update all the subcharts.")
fl.BoolVar(&o.download, "download", false, "only download the chart")
o.configFlags.AddFlags(fl)

if err := cmd.MarkFlagRequired("chartName"); err != nil {
panic(err)
}

if err := cmd.MarkFlagRequired("chartVersion"); err != nil {
panic(err)
}

return cmd
}

// Complete parses the arguments and necessary flags to options
func (c *options) Complete(cmd *cobra.Command, args []string) error {
var err error
if c.chartName == "" && c.chartVersion == "" {
if c.chartName == "" || c.chartVersion == "" {
return errNotEnoughParameters
}

Expand Down Expand Up @@ -118,7 +132,7 @@ func (c *options) Run() error {

ctx := context.Background()

upgrader, err := helmutil.NewUpgrader(kubeClient, c.chartRepo, c.repoURL, c.chartName)
upgrader, err := helmutil.NewUpgrader(kubeClient, c.chartRepo, c.repoURL, c.chartName, c.chartList)
if err != nil {
return err
}
Expand Down
58 changes: 58 additions & 0 deletions cmd/kubectl-k8ssandra/helm/helm_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
package helm

import (
"testing"

"github.com/spf13/cobra"
"github.com/stretchr/testify/require"
"k8s.io/cli-runtime/pkg/genericiooptions"
)

func TestSimplestCRDCommand(t *testing.T) {
require := require.New(t)

cmd := NewUpgradeCmd(genericiooptions.NewTestIOStreamsDiscard())
cmd.RunE = func(cmd *cobra.Command, args []string) error {
return nil
}

cmd.Root().SetArgs([]string{"upgrade", "--chartName", "k8ssandra-operator", "--chartVersion", "1.0.0"})
require.NoError(cmd.Execute())
}

func TestMissingParamsCRDCommand(t *testing.T) {
require := require.New(t)

cmd := NewUpgradeCmd(genericiooptions.NewTestIOStreamsDiscard())
cmd.RunE = func(cmd *cobra.Command, args []string) error {
return nil
}

cmd.Root().SetArgs([]string{"upgrade", "--chartName", "k8ssandra-operator"})
require.Error(cmd.Execute())
}

func TestInvalidParamsCRDCommand(t *testing.T) {
require := require.New(t)

cmd := NewUpgradeCmd(genericiooptions.NewTestIOStreamsDiscard())
cmd.RunE = func(cmd *cobra.Command, args []string) error {
return nil
}

cmd.Root().SetArgs([]string{"upgrade", "--chartName", "k8ssandra-operator", "--chartTarget", "1.0.0"})
require.Error(cmd.Execute())
}

func TestAllParamsCRDCommand(t *testing.T) {
require := require.New(t)

cmd := NewUpgradeCmd(genericiooptions.NewTestIOStreamsDiscard())
cmd.RunE = func(cmd *cobra.Command, args []string) error {
return nil
}

cmd.Root().SetArgs([]string{"upgrade", "--chartName", "k8ssandra-operator", "--chartVersion", "1.0.0",
"--chartRepo", "devel", "--repoURL", "https://helm.k8ssandra.io/devel", "--download", "true", "--charts", "cass-operator", "--charts", "k8ssandra-operator,cass-operator"})
require.NoError(cmd.Execute())
}
54 changes: 44 additions & 10 deletions pkg/helmutil/crds.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,21 +20,27 @@ import (
"sigs.k8s.io/controller-runtime/pkg/client"
)

const (
AllSubCharts = "_"
)

// Upgrader is a utility to update the CRDs in a helm chart's pre-upgrade hook
type Upgrader struct {
client client.Client
repoName string
repoURL string
chartName string
subCharts []string
}

// NewUpgrader returns a new Upgrader client
func NewUpgrader(c client.Client, repoName, repoURL, chartName string) (*Upgrader, error) {
func NewUpgrader(c client.Client, repoName, repoURL, chartName string, subCharts []string) (*Upgrader, error) {
return &Upgrader{
client: c,
repoName: repoName,
repoURL: repoURL,
chartName: chartName,
subCharts: subCharts,
}, nil
}

Expand Down Expand Up @@ -73,12 +79,11 @@ func (u *Upgrader) Upgrade(ctx context.Context, chartVersion string) ([]unstruct
crds := make([]unstructured.Unstructured, 0)

// For each dir under the charts subdir, check the "crds/"
paths, _ := findCRDDirs(chartDir)
paths, _ := findCRDDirs(chartDir, u.subCharts)

for _, path := range paths {
log.Debug("Processing CustomResourceDefinition directory", "path", path)
err = parseChartCRDs(&crds, path)
if err != nil {
if err := parseChartCRDs(&crds, path); err != nil {
return nil, err
}
}
Expand Down Expand Up @@ -106,18 +111,47 @@ func (u *Upgrader) Upgrade(ctx context.Context, chartVersion string) ([]unstruct
return crds, err
}

func findCRDDirs(chartDir string) ([]string, error) {
func findCRDDirs(chartDir string, subCharts []string) ([]string, error) {
chartsList := make(map[string]struct{})
for _, chart := range subCharts {
chartsList[chart] = struct{}{}
}

chartFilter := func(path string, info os.FileInfo) bool {
if !info.IsDir() || filepath.Base(path) != "crds" {
return false
}

chartParts := strings.Split(filepath.Clean(path), string(os.PathSeparator))
chartName := chartParts[len(chartParts)-2]
subChart := false
if len(chartParts) > 3 {
subChart = chartParts[len(chartParts)-3] == "charts"
}

if !subChart {
return true
}

if _, found := chartsList[AllSubCharts]; found {
return true
}

if _, found := chartsList[chartName]; found {
return true
}

return false
}
dirs := make([]string, 0)
err := filepath.Walk(chartDir, func(path string, info os.FileInfo, err error) error {
if err != nil {
return err
}
if info.IsDir() {
if strings.HasSuffix(path, "crds") {
dirs = append(dirs, path)
}
return nil
if chartFilter(path, info) {
dirs = append(dirs, path)
}

return nil
})
return dirs, err
Expand Down
2 changes: 1 addition & 1 deletion pkg/helmutil/crds_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ func TestUpgradingCRDs(t *testing.T) {
require.NoError(cleanCache("k8ssandra", chartName))

// creating new upgrader
u, err := helmutil.NewUpgrader(kubeClient, helmutil.K8ssandraRepoName, helmutil.StableK8ssandraRepoURL, chartName)
u, err := helmutil.NewUpgrader(kubeClient, helmutil.K8ssandraRepoName, helmutil.StableK8ssandraRepoURL, chartName, []string{})
require.NoError(err)

crds, err := u.Upgrade(context.TODO(), "0.42.0")
Expand Down
34 changes: 32 additions & 2 deletions pkg/helmutil/crds_unit_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,20 +15,50 @@ func TestFindCRDDirs(t *testing.T) {

require.NoError(os.MkdirAll(chartDir+"/downstream-operator/crds", 0755))

dirs, err := findCRDDirs(chartDir)
dirs, err := findCRDDirs(chartDir, []string{"downstream-operator"})
require.NoError(err)

require.Len(dirs, 1)
require.Equal(chartDir+"/downstream-operator/crds", dirs[0])

dirs, err = findCRDDirs(chartDir, []string{""})
require.NoError(err)

require.Len(dirs, 1)
require.Equal(chartDir+"/downstream-operator/crds", dirs[0])

dirs, err = findCRDDirs(chartDir, nil)
require.NoError(err)

require.Len(dirs, 1)
require.Equal(chartDir+"/downstream-operator/crds", dirs[0])

require.NoError(os.MkdirAll(chartDir+"/downstream-operator/charts/k8ssandra-operator/crds", 0755))
require.NoError(os.MkdirAll(chartDir+"/downstream-operator/charts/k8ssandra-operator/charts/cass-operator/crds", 0755))
require.NoError(os.MkdirAll(chartDir+"/downstream-operator/charts/third-party-operator/crds", 0755))
dirs, err = findCRDDirs(chartDir, []string{AllSubCharts})
require.NoError(err)

dirs, err = findCRDDirs(chartDir)
require.Len(dirs, 4)

dirs, err = findCRDDirs(chartDir, []string{"k8ssandra-operator", "cass-operator"})
require.NoError(err)

require.Len(dirs, 3)
require.Contains(dirs, chartDir+"/downstream-operator/crds")
require.Contains(dirs, chartDir+"/downstream-operator/charts/k8ssandra-operator/crds")
require.Contains(dirs, chartDir+"/downstream-operator/charts/k8ssandra-operator/charts/cass-operator/crds")

dirs, err = findCRDDirs(chartDir, []string{"k8ssandra-operator"})
require.NoError(err)

require.Len(dirs, 2)
require.Contains(dirs, chartDir+"/downstream-operator/crds")
require.Contains(dirs, chartDir+"/downstream-operator/charts/k8ssandra-operator/crds")

dirs, err = findCRDDirs(chartDir, []string{""})
require.NoError(err)

require.Len(dirs, 1)
require.Contains(dirs, chartDir+"/downstream-operator/crds")
}
Loading