Skip to content

Commit 164e5ac

Browse files
committed
feat: helm chart directory can be configured
Per default, helm-charts will get generated under dist/ directory. Via the newly introduced --directory flag it's now possible to define an alternative directory (e.g.: chart) fixes #4320 Signed-off-by: Mario Constanti <mario.constanti@mercedes-benz.com>
1 parent 096a743 commit 164e5ac

File tree

20 files changed

+179
-90
lines changed

20 files changed

+179
-90
lines changed

.golangci.yml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ linters:
1313
- goconst
1414
- gocyclo
1515
- govet
16+
- importas
1617
- ineffassign
1718
- lll
1819
- misspell
@@ -27,6 +28,10 @@ linters:
2728
- wrapcheck
2829
- whitespace
2930
settings:
31+
importas:
32+
alias:
33+
- pkg: sigs.k8s.io/kubebuilder/v4/pkg/plugins/optional/helm/v1alpha
34+
alias: helmv1alpha
3035
ginkgolinter:
3136
forbid-focus-container: true
3237
forbid-spec-pollution: true

cmd/cmd.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ import (
2828
deployimagev1alpha1 "sigs.k8s.io/kubebuilder/v4/pkg/plugins/golang/deploy-image/v1alpha1"
2929
golangv4 "sigs.k8s.io/kubebuilder/v4/pkg/plugins/golang/v4"
3030
grafanav1alpha1 "sigs.k8s.io/kubebuilder/v4/pkg/plugins/optional/grafana/v1alpha"
31-
helmv1alpha1 "sigs.k8s.io/kubebuilder/v4/pkg/plugins/optional/helm/v1alpha"
31+
helmv1alpha "sigs.k8s.io/kubebuilder/v4/pkg/plugins/optional/helm/v1alpha"
3232
)
3333

3434
func init() {
@@ -62,7 +62,7 @@ func Run() {
6262
&kustomizecommonv2.Plugin{},
6363
&deployimagev1alpha1.Plugin{},
6464
&grafanav1alpha1.Plugin{},
65-
&helmv1alpha1.Plugin{},
65+
&helmv1alpha.Plugin{},
6666
),
6767
cli.WithPlugins(externalPlugins...),
6868
cli.WithDefaultPlugins(cfgv3.Version, gov4Bundle),

pkg/cli/alpha/internal/generate.go

Lines changed: 39 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,8 @@ import (
3434
"sigs.k8s.io/kubebuilder/v4/pkg/plugin"
3535
"sigs.k8s.io/kubebuilder/v4/pkg/plugin/util"
3636
"sigs.k8s.io/kubebuilder/v4/pkg/plugins/golang/deploy-image/v1alpha1"
37-
"sigs.k8s.io/kubebuilder/v4/pkg/plugins/optional/grafana/v1alpha"
38-
hemlv1alpha "sigs.k8s.io/kubebuilder/v4/pkg/plugins/optional/helm/v1alpha"
37+
grafanav1alpha "sigs.k8s.io/kubebuilder/v4/pkg/plugins/optional/grafana/v1alpha"
38+
helmv1alpha "sigs.k8s.io/kubebuilder/v4/pkg/plugins/optional/helm/v1alpha"
3939
)
4040

4141
// Generate store the required info for the command
@@ -110,8 +110,8 @@ func (opts *Generate) Generate() error {
110110
}
111111

112112
if hasHelmPlugin(projectConfig) {
113-
if err = kubebuilderHelmEdit(); err != nil {
114-
return fmt.Errorf("error editing Helm plugin: %w", err)
113+
if err = migrateHelmPlugin(projectConfig); err != nil {
114+
return fmt.Errorf("error migrating Helm plugin: %w", err)
115115
}
116116
}
117117

@@ -226,7 +226,7 @@ func kubebuilderCreate(s store.Store) error {
226226
// Migrates the Grafana plugin.
227227
func migrateGrafanaPlugin(s store.Store, src, des string) error {
228228
var grafanaPlugin struct{}
229-
err := s.Config().DecodePluginConfig(plugin.KeyFor(v1alpha.Plugin{}), grafanaPlugin)
229+
err := s.Config().DecodePluginConfig(plugin.KeyFor(grafanav1alpha.Plugin{}), grafanaPlugin)
230230
if errors.As(err, &config.PluginKeyNotFoundError{}) {
231231
log.Info("Grafana plugin not found, skipping migration")
232232
return nil
@@ -481,28 +481,58 @@ func grafanaConfigMigrate(src, des string) error {
481481

482482
// Edits the project to include the Grafana plugin.
483483
func kubebuilderGrafanaEdit() error {
484-
args := []string{"edit", "--plugins", plugin.KeyFor(v1alpha.Plugin{})}
484+
args := []string{"edit", "--plugins", plugin.KeyFor(grafanav1alpha.Plugin{})}
485485
if err := util.RunCmd("kubebuilder edit", "kubebuilder", args...); err != nil {
486486
return fmt.Errorf("failed to run edit subcommand for Grafana plugin: %w", err)
487487
}
488488
return nil
489489
}
490490

491+
// Migrates the Helm plugin.
492+
func migrateHelmPlugin(s store.Store) error {
493+
var helmPlugin helmv1alpha.PluginConfig
494+
495+
err := s.Config().DecodePluginConfig(plugin.KeyFor(helmv1alpha.Plugin{}), &helmPlugin)
496+
if errors.As(err, &config.PluginKeyNotFoundError{}) {
497+
log.Info("Helm plugin not found, skipping migration")
498+
return nil
499+
} else if err != nil {
500+
return fmt.Errorf("failed to decode Helm plugin config: %w", err)
501+
}
502+
503+
return kubebuilderHelmEdit(helmPlugin)
504+
}
505+
491506
// Edits the project to include the Helm plugin.
492-
func kubebuilderHelmEdit() error {
493-
args := []string{"edit", "--plugins", plugin.KeyFor(hemlv1alpha.Plugin{})}
507+
func kubebuilderHelmEdit(resourceData helmv1alpha.PluginConfig) error {
508+
args := []string{"edit", "--plugins", plugin.KeyFor(helmv1alpha.Plugin{})}
509+
args = append(args, getHelmOptions(resourceData)...)
494510
if err := util.RunCmd("kubebuilder edit", "kubebuilder", args...); err != nil {
495511
return fmt.Errorf("failed to run edit subcommand for Helm plugin: %w", err)
496512
}
497513
return nil
498514
}
499515

516+
// Gets the options for Helm resource.
517+
// If the directory is not the default, it sets the directory option.
518+
// otherwise, it returns an empty slice which then use the default value from the edit/init subcommand.
519+
func getHelmOptions(resourceData helmv1alpha.PluginConfig) []string {
520+
var args []string
521+
522+
if resourceData.Options.Directory != helmv1alpha.HelmDefaultTargetDirectory {
523+
log.Info("setting directory for Helm chart")
524+
args = append(args, fmt.Sprintf("--directory=%s", resourceData.Options.Directory))
525+
}
526+
527+
return args
528+
}
529+
500530
// hasHelmPlugin checks if the Helm plugin is present by inspecting the plugin chain or configuration.
501531
func hasHelmPlugin(cfg store.Store) bool {
502532
var pluginConfig map[string]interface{}
503533

504534
// Decode the Helm plugin configuration to check if it's present
505-
err := cfg.Config().DecodePluginConfig(plugin.KeyFor(hemlv1alpha.Plugin{}), &pluginConfig)
535+
err := cfg.Config().DecodePluginConfig(plugin.KeyFor(helmv1alpha.Plugin{}), &pluginConfig)
506536
if err != nil {
507537
// If the Helm plugin is not found, return false
508538
if errors.As(err, &config.PluginKeyNotFoundError{}) {

pkg/plugins/optional/helm/v1alpha/commons.go

Lines changed: 0 additions & 38 deletions
This file was deleted.

pkg/plugins/optional/helm/v1alpha/edit.go

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ limitations under the License.
1717
package v1alpha
1818

1919
import (
20+
"errors"
2021
"fmt"
2122

2223
"github.com/spf13/pflag"
@@ -29,8 +30,9 @@ import (
2930
var _ plugin.EditSubcommand = &editSubcommand{}
3031

3132
type editSubcommand struct {
32-
config config.Config
33-
force bool
33+
config config.Config
34+
force bool
35+
directory string
3436
}
3537

3638
//nolint:lll
@@ -66,6 +68,7 @@ manifests in the chart align with the latest changes.
6668

6769
func (p *editSubcommand) BindFlags(fs *pflag.FlagSet) {
6870
fs.BoolVar(&p.force, "force", false, "if true, regenerates all the files")
71+
fs.StringVar(&p.directory, "directory", HelmDefaultTargetDirectory, "domain for groups")
6972
}
7073

7174
func (p *editSubcommand) InjectConfig(c config.Config) error {
@@ -74,13 +77,30 @@ func (p *editSubcommand) InjectConfig(c config.Config) error {
7477
}
7578

7679
func (p *editSubcommand) Scaffold(fs machinery.Filesystem) error {
77-
scaffolder := scaffolds.NewHelmScaffolder(p.config, p.force)
80+
scaffolder := scaffolds.NewHelmScaffolder(p.config, p.force, p.directory)
7881
scaffolder.InjectFS(fs)
7982
err := scaffolder.Scaffold()
8083
if err != nil {
8184
return fmt.Errorf("error scaffolding Helm chart: %w", err)
8285
}
8386

8487
// Track the resources following a declarative approach
85-
return insertPluginMetaToConfig(p.config, pluginConfig{})
88+
cfg := PluginConfig{}
89+
if err = p.config.DecodePluginConfig(pluginKey, &cfg); errors.As(err, &config.UnsupportedFieldError{}) {
90+
// Skip tracking as the config doesn't support per-plugin configuration
91+
return nil
92+
} else if err != nil && !errors.As(err, &config.PluginKeyNotFoundError{}) {
93+
// Fail unless the key wasn't found, which just means it is the first resource tracked
94+
return fmt.Errorf("error decoding plugin configuration: %w", err)
95+
}
96+
97+
cfg.Options = options{
98+
Directory: p.directory,
99+
}
100+
101+
if err = p.config.EncodePluginConfig(pluginKey, cfg); err != nil {
102+
return fmt.Errorf("error encoding plugin configuration: %w", err)
103+
}
104+
105+
return nil
86106
}

pkg/plugins/optional/helm/v1alpha/plugin.go

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,15 @@ import (
2424
"sigs.k8s.io/kubebuilder/v4/pkg/plugins"
2525
)
2626

27-
const pluginName = "helm." + plugins.DefaultNameQualifier
27+
const (
28+
pluginName = "helm." + plugins.DefaultNameQualifier
29+
30+
// HelmDefaultTargetDirectory is the default directory where the Helm chart will be scaffolded
31+
// This is used in the init subcommand to scaffold the Helm chart.
32+
// It is also used in the edit subcommand to add or edit a Helm chart.
33+
// It is set to "dist" to match the default target directory for other plugins.
34+
HelmDefaultTargetDirectory = "dist"
35+
)
2836

2937
var (
3038
pluginVersion = plugin.Version{Number: 1, Stage: stage.Alpha}
@@ -39,7 +47,15 @@ type Plugin struct {
3947

4048
var _ plugin.Edit = Plugin{}
4149

42-
type pluginConfig struct{}
50+
type PluginConfig struct {
51+
// Options contains the options for the Helm plugin
52+
Options options `json:"options,omitempty"`
53+
}
54+
55+
type options struct {
56+
// Directory is the directory where the Helm chart will be scaffolded
57+
Directory string `json:"directory,omitempty"`
58+
}
4359

4460
// Name returns the name of the plugin
4561
func (Plugin) Name() string { return pluginName }

pkg/plugins/optional/helm/v1alpha/scaffolds/edit.go

Lines changed: 40 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -50,13 +50,16 @@ type editScaffolder struct {
5050
fs machinery.Filesystem
5151

5252
force bool
53+
54+
directory string
5355
}
5456

5557
// NewHelmScaffolder returns a new Scaffolder for HelmPlugin
56-
func NewHelmScaffolder(cfg config.Config, force bool) plugins.Scaffolder {
58+
func NewHelmScaffolder(cfg config.Config, force bool, dir string) plugins.Scaffolder {
5759
return &editScaffolder{
58-
config: cfg,
59-
force: force,
60+
config: cfg,
61+
force: force,
62+
directory: dir,
6063
}
6164
}
6265

@@ -83,37 +86,57 @@ func (s *editScaffolder) Scaffold() error {
8386
hasWebhooks := hasWebhooksWith(s.config) || (len(mutatingWebhooks) > 0 && len(validatingWebhooks) > 0)
8487

8588
buildScaffold := []machinery.Builder{
86-
&github.HelmChartCI{},
87-
&templates.HelmChart{},
89+
&github.HelmChartCI{
90+
Directory: s.directory,
91+
},
92+
&templates.HelmChart{
93+
Directory: s.directory,
94+
},
8895
&templates.HelmValues{
8996
HasWebhooks: hasWebhooks,
9097
DeployImages: imagesEnvVars,
9198
Force: s.force,
99+
Directory: s.directory,
100+
},
101+
&templates.HelmIgnore{
102+
Directory: s.directory,
103+
},
104+
&charttemplates.HelmHelpers{
105+
Directory: s.directory,
92106
},
93-
&templates.HelmIgnore{},
94-
&charttemplates.HelmHelpers{},
95107
&manager.Deployment{
96108
Force: s.force,
97109
DeployImages: len(imagesEnvVars) > 0,
98110
HasWebhooks: hasWebhooks,
111+
Directory: s.directory,
112+
},
113+
&templatescertmanager.Certificate{
114+
HasWebhooks: hasWebhooks,
115+
Directory: s.directory,
116+
},
117+
&templatesmetrics.Service{
118+
Directory: s.directory,
119+
},
120+
&prometheus.Monitor{
121+
Directory: s.directory,
99122
},
100-
&templatescertmanager.Certificate{HasWebhooks: hasWebhooks},
101-
&templatesmetrics.Service{},
102-
&prometheus.Monitor{},
103123
}
104124

105125
if len(mutatingWebhooks) > 0 || len(validatingWebhooks) > 0 {
106126
buildScaffold = append(buildScaffold,
107127
&templateswebhooks.Template{
108128
MutatingWebhooks: mutatingWebhooks,
109129
ValidatingWebhooks: validatingWebhooks,
130+
Directory: s.directory,
110131
},
111132
)
112133
}
113134

114135
if hasWebhooks {
115136
buildScaffold = append(buildScaffold,
116-
&templateswebhooks.Service{},
137+
&templateswebhooks.Service{
138+
Directory: s.directory,
139+
},
117140
)
118141
}
119142

@@ -122,9 +145,9 @@ func (s *editScaffolder) Scaffold() error {
122145
}
123146

124147
// Copy relevant files from config/ to dist/chart/templates/
125-
err = s.copyConfigFiles()
148+
err = s.copyConfigFiles(s.directory)
126149
if err != nil {
127-
return fmt.Errorf("failed to copy manifests from config to dist/chart/templates/: %w", err)
150+
return fmt.Errorf("failed to copy manifests from config %s/chart/templates/: %w", s.directory, err)
128151
}
129152

130153
return nil
@@ -227,15 +250,15 @@ func (s *editScaffolder) extractWebhooksFromGeneratedFiles() (mutatingWebhooks [
227250
}
228251

229252
// Helper function to copy files from config/ to dist/chart/templates/
230-
func (s *editScaffolder) copyConfigFiles() error {
253+
func (s *editScaffolder) copyConfigFiles(targetDirectory string) error {
231254
configDirs := []struct {
232255
SrcDir string
233256
DestDir string
234257
SubDir string
235258
}{
236-
{"config/rbac", "dist/chart/templates/rbac", "rbac"},
237-
{"config/crd/bases", "dist/chart/templates/crd", "crd"},
238-
{"config/network-policy", "dist/chart/templates/network-policy", "networkPolicy"},
259+
{"config/rbac", targetDirectory + "/chart/templates/rbac", "rbac"},
260+
{"config/crd/bases", targetDirectory + "/chart/templates/crd", "crd"},
261+
{"config/network-policy", targetDirectory + "/chart/templates/network-policy", "networkPolicy"},
239262
}
240263

241264
for _, dir := range configDirs {

pkg/plugins/optional/helm/v1alpha/scaffolds/internal/templates/chart-templates/cert-manager/certificate.go

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,12 +30,14 @@ type Certificate struct {
3030

3131
// HasWebhooks is true when webhooks were found in the config
3232
HasWebhooks bool
33+
// Directory is the directory where the Helm chart will be scaffolded
34+
Directory string
3335
}
3436

3537
// SetTemplateDefaults sets the default template configuration
3638
func (f *Certificate) SetTemplateDefaults() error {
3739
if f.Path == "" {
38-
f.Path = filepath.Join("dist", "chart", "templates", "certmanager", "certificate.yaml")
40+
f.Path = filepath.Join(f.Directory, "chart", "templates", "certmanager", "certificate.yaml")
3941
}
4042

4143
f.TemplateBody = certificateTemplate

0 commit comments

Comments
 (0)