Skip to content

Commit

Permalink
add helm plugin to distribute projects
Browse files Browse the repository at this point in the history
  • Loading branch information
camilamacedo86 committed Oct 22, 2024
1 parent eae8b21 commit 7276a0c
Show file tree
Hide file tree
Showing 327 changed files with 696 additions and 25,140 deletions.
2 changes: 2 additions & 0 deletions cmd/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ import (
deployimagev1alpha1 "sigs.k8s.io/kubebuilder/v4/pkg/plugins/golang/deploy-image/v1alpha1"
golangv4 "sigs.k8s.io/kubebuilder/v4/pkg/plugins/golang/v4"
grafanav1alpha1 "sigs.k8s.io/kubebuilder/v4/pkg/plugins/optional/grafana/v1alpha"
helmv1alpha1 "sigs.k8s.io/kubebuilder/v4/pkg/plugins/optional/helm/v1alpha"
)

func init() {
Expand Down Expand Up @@ -61,6 +62,7 @@ func main() {
&kustomizecommonv2.Plugin{},
&deployimagev1alpha1.Plugin{},
&grafanav1alpha1.Plugin{},
&helmv1alpha1.Plugin{},
),
cli.WithPlugins(externalPlugins...),
cli.WithDefaultPlugins(cfgv3.Version, gov4Bundle),
Expand Down
57 changes: 57 additions & 0 deletions pkg/plugins/optional/helm/v1alpha/edit.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
/*
Copyright 2024 The Kubernetes 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 v1alpha

import (
"fmt"
"github.com/spf13/pflag"
"sigs.k8s.io/kubebuilder/v4/pkg/config"
"sigs.k8s.io/kubebuilder/v4/pkg/machinery"
"sigs.k8s.io/kubebuilder/v4/pkg/plugin"
"sigs.k8s.io/kubebuilder/v4/pkg/plugins/optional/helm/v1alpha/scaffolds"
)

var _ plugin.EditSubcommand = &editSubcommand{}

type editSubcommand struct {
config config.Config
force bool
}

func (p *editSubcommand) UpdateMetadata(cliMeta plugin.CLIMetadata, subcmdMeta *plugin.SubcommandMetadata) {
subcmdMeta.Description = `Initialize a helm chart to distribute the project under dist/
`
subcmdMeta.Examples = fmt.Sprintf(` # Initialize a helm chart to distribute the project under dist/
%[1]s edit --plugins helm/v1alpha
`, cliMeta.CommandName)
}

func (p *editSubcommand) BindFlags(fs *pflag.FlagSet) {
fs.BoolVar(&p.force, "force", true, "if true, run re-generate the files")
}

func (p *editSubcommand) InjectConfig(c config.Config) error {
p.config = c
return nil
}

func (p *editSubcommand) Scaffold(fs machinery.Filesystem) error {
scaffolder := scaffolds.NewInitScaffolder()
scaffolder.InjectFS(fs)
return scaffolder.Scaffold()
}
53 changes: 53 additions & 0 deletions pkg/plugins/optional/helm/v1alpha/init.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
/*
Copyright 2024 The Kubernetes 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 v1alpha

import (
"fmt"

"sigs.k8s.io/kubebuilder/v4/pkg/config"
"sigs.k8s.io/kubebuilder/v4/pkg/machinery"
"sigs.k8s.io/kubebuilder/v4/pkg/plugin"
"sigs.k8s.io/kubebuilder/v4/pkg/plugins/optional/grafana/v1alpha/scaffolds"
)

var _ plugin.InitSubcommand = &initSubcommand{}

type initSubcommand struct {
config config.Config
}

func (p *initSubcommand) UpdateMetadata(cliMeta plugin.CLIMetadata, subcmdMeta *plugin.SubcommandMetadata) {
subcmdMeta.Description = `Initialize a helm chart to distribute the project under dist/
`
subcmdMeta.Examples = fmt.Sprintf(` # Initialize a helm chart to distribute the project under dist/
%[1]s init --plugins helm/v1alpha
`, cliMeta.CommandName)
}

func (p *initSubcommand) InjectConfig(c config.Config) error {
p.config = c
return nil
}

func (p *initSubcommand) Scaffold(fs machinery.Filesystem) error {

scaffolder := scaffolds.NewInitScaffolder()
scaffolder.InjectFS(fs)
return scaffolder.Scaffold()
}
64 changes: 64 additions & 0 deletions pkg/plugins/optional/helm/v1alpha/plugin.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
/*
Copyright 2024 The Kubernetes 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 v1alpha

import (
"sigs.k8s.io/kubebuilder/v4/pkg/config"
cfgv3 "sigs.k8s.io/kubebuilder/v4/pkg/config/v3"
"sigs.k8s.io/kubebuilder/v4/pkg/model/stage"
"sigs.k8s.io/kubebuilder/v4/pkg/plugin"
"sigs.k8s.io/kubebuilder/v4/pkg/plugins"
)

const pluginName = "helm." + plugins.DefaultNameQualifier

var (
pluginVersion = plugin.Version{Number: 1, Stage: stage.Alpha}
supportedProjectVersions = []config.Version{cfgv3.Version}
pluginKey = plugin.KeyFor(Plugin{})

Check failure on line 32 in pkg/plugins/optional/helm/v1alpha/plugin.go

View workflow job for this annotation

GitHub Actions / golangci-lint

var `pluginKey` is unused (unused)
)

// Plugin implements the plugin.Full interface
type Plugin struct {
initSubcommand
editSubcommand
}

var (
_ plugin.Init = Plugin{}
)

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

// Version returns the version of the grafana plugin
func (Plugin) Version() plugin.Version { return pluginVersion }

// SupportedProjectVersions returns an array with all project versions supported by the plugin
func (Plugin) SupportedProjectVersions() []config.Version { return supportedProjectVersions }

// GetInitSubcommand will return the subcommand which is responsible for initializing and scaffolding grafana manifests
func (p Plugin) GetInitSubcommand() plugin.InitSubcommand { return &p.initSubcommand }

// GetEditSubcommand will return the subcommand which is responsible for adding grafana manifests
func (p Plugin) GetEditSubcommand() plugin.EditSubcommand { return &p.editSubcommand }

type pluginConfig struct{}

Check failure on line 60 in pkg/plugins/optional/helm/v1alpha/plugin.go

View workflow job for this annotation

GitHub Actions / golangci-lint

type `pluginConfig` is unused (unused)

func (p Plugin) DeprecationWarning() string {
return ""
}
145 changes: 145 additions & 0 deletions pkg/plugins/optional/helm/v1alpha/scaffolds/init.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
/*
Copyright 2022 The Kubernetes 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 scaffolds

import (
"fmt"
log "github.com/sirupsen/logrus"
"io/ioutil"

Check failure on line 22 in pkg/plugins/optional/helm/v1alpha/scaffolds/init.go

View workflow job for this annotation

GitHub Actions / golangci-lint

SA1019: "io/ioutil" has been deprecated since Go 1.19: As of Go 1.16, the same functionality is now provided by package [io] or package [os], and those implementations should be preferred in new code. See the specific function documentation for details. (staticcheck)
"os"
"path/filepath"
"sigs.k8s.io/kubebuilder/v4/pkg/plugins/optional/helm/v1alpha/scaffolds/internal/templates"
"strings"

"sigs.k8s.io/kubebuilder/v4/pkg/machinery"
"sigs.k8s.io/kubebuilder/v4/pkg/plugins"
)

var _ plugins.Scaffolder = &initScaffolder{}

type initScaffolder struct {
fs machinery.Filesystem
}

// NewInitScaffolder returns a new Scaffolder for project initialization operations
func NewInitScaffolder() plugins.Scaffolder {
return &initScaffolder{}
}

// InjectFS implements cmdutil.Scaffolder
func (s *initScaffolder) InjectFS(fs machinery.Filesystem) {
s.fs = fs
}

// Scaffold implements cmdutil.Scaffolder
func (s *initScaffolder) Scaffold() error {
log.Println("Generating Helm Chart to distribute project")

scaffold := machinery.NewScaffold(s.fs)

err := scaffold.Execute(
&templates.HelmChart{},
&templates.HelmValues{},
&templates.HelmIgnore{},
)
if err != nil {
return err
}

// Copy all relevant files from config/ to chart/templates/
err = copyConfigFiles()
if err != nil {
return err
}
return nil
}

// Helper function to copy files from config/ to dist/chart/templates/
func copyConfigFiles() error {
// Define the source directories and destination directories under dist/chart/templates
configDirs := []struct {
SrcDir string
DestDir string
SubDir string
}{
{"config/rbac", "dist/chart/templates/rbac", "rbac"},
{"config/manager", "dist/chart/templates/manager", "controllerManager"},
{"config/webhook", "dist/chart/templates/webhook", "webhook"},
{"config/crd/bases", "dist/chart/templates/crds", "crd"},
{"config/prometheus", "dist/chart/templates/prometheus", "prometheus"},
{"config/certmanager", "dist/chart/templates/certmanager", "certmanager"},
{"config/network-policy", "dist/chart/templates/network-policy", "networkPolicy"},
}

// Copy all YAML files in each directory
for _, dir := range configDirs {
files, err := filepath.Glob(filepath.Join(dir.SrcDir, "*.yaml"))
if err != nil {
return err
}

for _, srcFile := range files {
destFile := filepath.Join(dir.DestDir, filepath.Base(srcFile))
err := copyFileWithHelmLogic(srcFile, destFile, dir.SubDir)
if err != nil {
return err
}
}
}

return nil
}

// copyFileWithHelmLogic reads the source file, wraps it with Helm logic, and writes it to the destination
func copyFileWithHelmLogic(srcFile, destFile, subDir string) error {
// Ensure the source file exists
if _, err := os.Stat(srcFile); os.IsNotExist(err) {
log.Printf("Source file does not exist: %s", srcFile)
return err
}

// Read the source file
content, err := ioutil.ReadFile(srcFile)
if err != nil {
log.Printf("Error reading source file: %s", srcFile)
return err
}

// Skip irrelevant files like kustomization.yaml
if strings.HasSuffix(srcFile, "kustomization.yaml") || strings.HasSuffix(srcFile, "kustomizeconfig.yaml") {
log.Printf("Skipping irrelevant file: %s", srcFile)
return nil
}

// Wrap the content with Helm conditional logic based on the subdirectory (e.g., "rbac", "manager")
wrappedContent := fmt.Sprintf("{{- if .Values.%s.create }}\n%s\n{{- end }}\n", subDir, string(content))

// Ensure the destination directory exists
if err := os.MkdirAll(filepath.Dir(destFile), os.ModePerm); err != nil {
return err
}

// Write the wrapped content to the destination file
err = ioutil.WriteFile(destFile, []byte(wrappedContent), os.ModePerm)
if err != nil {
log.Printf("Error writing destination file: %s", destFile)
return err
}

log.Printf("Successfully copied %s to %s", srcFile, destFile)
return nil
}
Loading

0 comments on commit 7276a0c

Please sign in to comment.