Skip to content

Commit 6b491e7

Browse files
add helm plugin to distribute projects
1 parent eae8b21 commit 6b491e7

File tree

89 files changed

+3890
-9
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

89 files changed

+3890
-9
lines changed

cmd/main.go

+2
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ import (
3030
deployimagev1alpha1 "sigs.k8s.io/kubebuilder/v4/pkg/plugins/golang/deploy-image/v1alpha1"
3131
golangv4 "sigs.k8s.io/kubebuilder/v4/pkg/plugins/golang/v4"
3232
grafanav1alpha1 "sigs.k8s.io/kubebuilder/v4/pkg/plugins/optional/grafana/v1alpha"
33+
helmv1alpha1 "sigs.k8s.io/kubebuilder/v4/pkg/plugins/optional/helm/v1alpha"
3334
)
3435

3536
func init() {
@@ -61,6 +62,7 @@ func main() {
6162
&kustomizecommonv2.Plugin{},
6263
&deployimagev1alpha1.Plugin{},
6364
&grafanav1alpha1.Plugin{},
65+
&helmv1alpha1.Plugin{},
6466
),
6567
cli.WithPlugins(externalPlugins...),
6668
cli.WithDefaultPlugins(cfgv3.Version, gov4Bundle),
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
/*
2+
Copyright 2024 The Kubernetes Authors.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
package v1alpha
18+
19+
import (
20+
"errors"
21+
22+
"sigs.k8s.io/kubebuilder/v4/pkg/config"
23+
)
24+
25+
func InsertPluginMetaToConfig(target config.Config, cfg pluginConfig) error {
26+
err := target.DecodePluginConfig(pluginKey, cfg)
27+
if !errors.As(err, &config.UnsupportedFieldError{}) {
28+
29+
if err != nil && !errors.As(err, &config.PluginKeyNotFoundError{}) {
30+
return err
31+
}
32+
33+
if err = target.EncodePluginConfig(pluginKey, cfg); err != nil {
34+
return err
35+
}
36+
37+
}
38+
39+
return nil
40+
}
+68
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
/*
2+
Copyright 2024 The Kubernetes Authors.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
package v1alpha
18+
19+
import (
20+
"fmt"
21+
22+
"github.com/spf13/pflag"
23+
"sigs.k8s.io/kubebuilder/v4/pkg/config"
24+
"sigs.k8s.io/kubebuilder/v4/pkg/machinery"
25+
"sigs.k8s.io/kubebuilder/v4/pkg/plugin"
26+
"sigs.k8s.io/kubebuilder/v4/pkg/plugins/optional/helm/v1alpha/scaffolds"
27+
)
28+
29+
var _ plugin.EditSubcommand = &editSubcommand{}
30+
31+
type editSubcommand struct {
32+
config config.Config
33+
force bool
34+
}
35+
36+
func (p *editSubcommand) UpdateMetadata(cliMeta plugin.CLIMetadata, subcmdMeta *plugin.SubcommandMetadata) {
37+
subcmdMeta.Description = `Initialize a helm chart to distribute the project under dist/
38+
`
39+
subcmdMeta.Examples = fmt.Sprintf(` # Initialize a helm chart to distribute the project under dist/
40+
%[1]s edit --plugins helm/v1alpha
41+
42+
`, cliMeta.CommandName)
43+
}
44+
45+
func (p *editSubcommand) BindFlags(fs *pflag.FlagSet) {
46+
fs.BoolVar(&p.force, "force", true, "if true, run re-generate the files")
47+
}
48+
49+
func (p *editSubcommand) InjectConfig(c config.Config) error {
50+
p.config = c
51+
return nil
52+
}
53+
54+
func (p *editSubcommand) Scaffold(fs machinery.Filesystem) error {
55+
scaffolder := scaffolds.NewInitScaffolder()
56+
scaffolder.InjectFS(fs)
57+
err := scaffolder.Scaffold()
58+
if err != nil {
59+
return err
60+
}
61+
62+
// Track the resources following a declarative approach
63+
if err := InsertPluginMetaToConfig(p.config, pluginConfig{}); err != nil {
64+
return err
65+
}
66+
67+
return nil
68+
}
+62
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
/*
2+
Copyright 2024 The Kubernetes Authors.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
package v1alpha
18+
19+
import (
20+
"fmt"
21+
22+
"sigs.k8s.io/kubebuilder/v4/pkg/config"
23+
"sigs.k8s.io/kubebuilder/v4/pkg/machinery"
24+
"sigs.k8s.io/kubebuilder/v4/pkg/plugin"
25+
"sigs.k8s.io/kubebuilder/v4/pkg/plugins/optional/grafana/v1alpha/scaffolds"
26+
)
27+
28+
var _ plugin.InitSubcommand = &initSubcommand{}
29+
30+
type initSubcommand struct {
31+
config config.Config
32+
}
33+
34+
func (p *initSubcommand) UpdateMetadata(cliMeta plugin.CLIMetadata, subcmdMeta *plugin.SubcommandMetadata) {
35+
subcmdMeta.Description = `Initialize a helm chart to distribute the project under dist/
36+
`
37+
subcmdMeta.Examples = fmt.Sprintf(` # Initialize a helm chart to distribute the project under dist/
38+
%[1]s init --plugins helm/v1alpha
39+
40+
`, cliMeta.CommandName)
41+
}
42+
43+
func (p *initSubcommand) InjectConfig(c config.Config) error {
44+
p.config = c
45+
return nil
46+
}
47+
48+
func (p *initSubcommand) Scaffold(fs machinery.Filesystem) error {
49+
scaffolder := scaffolds.NewInitScaffolder()
50+
scaffolder.InjectFS(fs)
51+
err := scaffolder.Scaffold()
52+
if err != nil {
53+
return err
54+
}
55+
56+
// Track the resources following a declarative approach
57+
if err := InsertPluginMetaToConfig(p.config, pluginConfig{}); err != nil {
58+
return err
59+
}
60+
61+
return nil
62+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
/*
2+
Copyright 2024 The Kubernetes Authors.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
package v1alpha
18+
19+
import (
20+
"sigs.k8s.io/kubebuilder/v4/pkg/config"
21+
cfgv3 "sigs.k8s.io/kubebuilder/v4/pkg/config/v3"
22+
"sigs.k8s.io/kubebuilder/v4/pkg/model/stage"
23+
"sigs.k8s.io/kubebuilder/v4/pkg/plugin"
24+
"sigs.k8s.io/kubebuilder/v4/pkg/plugins"
25+
)
26+
27+
const pluginName = "helm." + plugins.DefaultNameQualifier
28+
29+
var (
30+
pluginVersion = plugin.Version{Number: 1, Stage: stage.Alpha}
31+
supportedProjectVersions = []config.Version{cfgv3.Version}
32+
pluginKey = plugin.KeyFor(Plugin{})
33+
)
34+
35+
// Plugin implements the plugin.Full interface
36+
type Plugin struct {
37+
initSubcommand
38+
editSubcommand
39+
}
40+
41+
var (
42+
_ plugin.Init = Plugin{}
43+
)
44+
45+
// Name returns the name of the plugin
46+
func (Plugin) Name() string { return pluginName }
47+
48+
// Version returns the version of the grafana plugin
49+
func (Plugin) Version() plugin.Version { return pluginVersion }
50+
51+
// SupportedProjectVersions returns an array with all project versions supported by the plugin
52+
func (Plugin) SupportedProjectVersions() []config.Version { return supportedProjectVersions }
53+
54+
// GetInitSubcommand will return the subcommand which is responsible for initializing and scaffolding grafana manifests
55+
func (p Plugin) GetInitSubcommand() plugin.InitSubcommand { return &p.initSubcommand }
56+
57+
// GetEditSubcommand will return the subcommand which is responsible for adding grafana manifests
58+
func (p Plugin) GetEditSubcommand() plugin.EditSubcommand { return &p.editSubcommand }
59+
60+
type pluginConfig struct{}
61+
62+
func (p Plugin) DeprecationWarning() string {
63+
return ""
64+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,145 @@
1+
/*
2+
Copyright 2022 The Kubernetes Authors.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
package scaffolds
18+
19+
import (
20+
"fmt"
21+
"os"
22+
"path/filepath"
23+
"strings"
24+
25+
log "github.com/sirupsen/logrus"
26+
"sigs.k8s.io/kubebuilder/v4/pkg/plugins/optional/helm/v1alpha/scaffolds/internal/templates"
27+
28+
"sigs.k8s.io/kubebuilder/v4/pkg/machinery"
29+
"sigs.k8s.io/kubebuilder/v4/pkg/plugins"
30+
)
31+
32+
var _ plugins.Scaffolder = &initScaffolder{}
33+
34+
type initScaffolder struct {
35+
fs machinery.Filesystem
36+
}
37+
38+
// NewInitScaffolder returns a new Scaffolder for project initialization operations
39+
func NewInitScaffolder() plugins.Scaffolder {
40+
return &initScaffolder{}
41+
}
42+
43+
// InjectFS implements cmdutil.Scaffolder
44+
func (s *initScaffolder) InjectFS(fs machinery.Filesystem) {
45+
s.fs = fs
46+
}
47+
48+
// Scaffold implements cmdutil.Scaffolder
49+
func (s *initScaffolder) Scaffold() error {
50+
log.Println("Generating Helm Chart to distribute project")
51+
52+
scaffold := machinery.NewScaffold(s.fs)
53+
54+
err := scaffold.Execute(
55+
&templates.HelmChart{},
56+
&templates.HelmValues{},
57+
&templates.HelmIgnore{},
58+
)
59+
if err != nil {
60+
return err
61+
}
62+
63+
// Copy all relevant files from config/ to chart/templates/
64+
err = copyConfigFiles()
65+
if err != nil {
66+
return err
67+
}
68+
return nil
69+
}
70+
71+
// Helper function to copy files from config/ to dist/chart/templates/
72+
func copyConfigFiles() error {
73+
// Define the source directories and destination directories under dist/chart/templates
74+
configDirs := []struct {
75+
SrcDir string
76+
DestDir string
77+
SubDir string
78+
}{
79+
{"config/rbac", "dist/chart/templates/rbac", "rbac"},
80+
{"config/manager", "dist/chart/templates/manager", "controllerManager"},
81+
{"config/webhook", "dist/chart/templates/webhook", "webhook"},
82+
{"config/crd/bases", "dist/chart/templates/crds", "crd"},
83+
{"config/prometheus", "dist/chart/templates/prometheus", "prometheus"},
84+
{"config/certmanager", "dist/chart/templates/certmanager", "certmanager"},
85+
{"config/network-policy", "dist/chart/templates/network-policy", "networkPolicy"},
86+
}
87+
88+
// Copy all YAML files in each directory
89+
for _, dir := range configDirs {
90+
files, err := filepath.Glob(filepath.Join(dir.SrcDir, "*.yaml"))
91+
if err != nil {
92+
return err
93+
}
94+
95+
for _, srcFile := range files {
96+
destFile := filepath.Join(dir.DestDir, filepath.Base(srcFile))
97+
err := copyFileWithHelmLogic(srcFile, destFile, dir.SubDir)
98+
if err != nil {
99+
return err
100+
}
101+
}
102+
}
103+
104+
return nil
105+
}
106+
107+
// copyFileWithHelmLogic reads the source file, wraps it with Helm logic, and writes it to the destination
108+
func copyFileWithHelmLogic(srcFile, destFile, subDir string) error {
109+
// Ensure the source file exists
110+
if _, err := os.Stat(srcFile); os.IsNotExist(err) {
111+
log.Printf("Source file does not exist: %s", srcFile)
112+
return err
113+
}
114+
115+
// Read the source file
116+
content, err := os.ReadFile(srcFile)
117+
if err != nil {
118+
log.Printf("Error reading source file: %s", srcFile)
119+
return err
120+
}
121+
122+
// Skip irrelevant files like kustomization.yaml
123+
if strings.HasSuffix(srcFile, "kustomization.yaml") || strings.HasSuffix(srcFile, "kustomizeconfig.yaml") {
124+
log.Printf("Skipping irrelevant file: %s", srcFile)
125+
return nil
126+
}
127+
128+
// Wrap the content with Helm conditional logic based on the subdirectory (e.g., "rbac", "manager")
129+
wrappedContent := fmt.Sprintf("{{- if .Values.%s.create }}\n%s\n{{- end }}\n", subDir, string(content))
130+
131+
// Ensure the destination directory exists
132+
if err := os.MkdirAll(filepath.Dir(destFile), os.ModePerm); err != nil {
133+
return err
134+
}
135+
136+
// Write the wrapped content to the destination file
137+
err = os.WriteFile(destFile, []byte(wrappedContent), os.ModePerm)
138+
if err != nil {
139+
log.Printf("Error writing destination file: %s", destFile)
140+
return err
141+
}
142+
143+
log.Printf("Successfully copied %s to %s", srcFile, destFile)
144+
return nil
145+
}

0 commit comments

Comments
 (0)