diff --git a/.github/workflows/golangci-lint.yml b/.github/workflows/golangci-lint.yml new file mode 100644 index 0000000..4e8a171 --- /dev/null +++ b/.github/workflows/golangci-lint.yml @@ -0,0 +1,24 @@ +name: Go - Lint +on: + push: + branches: + - main + pull_request: + +permissions: + contents: read + +jobs: + golangci: + name: lint + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - uses: actions/setup-go@v4 + with: + go-version: '1.21' + cache: false + - name: golangci-lint + uses: golangci/golangci-lint-action@v3 + with: + version: v1.54 diff --git a/.golangci.yml b/.golangci.yml new file mode 100644 index 0000000..6032f4c --- /dev/null +++ b/.golangci.yml @@ -0,0 +1,62 @@ +linters-settings: + funlen: + lines: 100 + statements: 50 + gocyclo: + min-complexity: 15 + goimports: + local-prefixes: github.com/aabouzaid/kustomize-plugin-merger + govet: + check-shadowing: true + misspell: + locale: US + nolintlint: + allow-leading-space: false # require machine-readable nolint directives (with no leading space) + allow-unused: false # report any unused nolint directives + require-explanation: true # require an explanation for nolint directives + require-specific: false # don't require nolint directives to be specific about which linter is being skipped + revive: + confidence: 0 + +linters: + disable-all: true + enable: + - bodyclose + - dogsled + - dupl + - errcheck + - exportloopref + - funlen + - gochecknoinits + - gocritic + - goconst + - gocyclo + - gofumpt + - goimports + - revive + - rowserrcheck + - goprintffuncname + - gosec + - gosimple + - govet + - ineffassign + - misspell + - nakedret + - noctx + - nolintlint + - staticcheck + - stylecheck + - sqlclosecheck + - typecheck + - unconvert + - unparam + - unused + - whitespace + +issues: + # Disable default exclusions. + # https://golangci-lint.run/usage/false-positives/#default-exclusions + exclude-use-default: false + exclude: + - "package-comments: .+" + - "ST1000: package comment should be of the form" diff --git a/Makefile b/Makefile index 1bfd3c8..ea5fb71 100644 --- a/Makefile +++ b/Makefile @@ -15,3 +15,7 @@ schema.generate: sed -e 's/CustomResourceDefinition/KRMFunctionDefinition/g' \ -e 's|apiextensions.k8s.io/v1|config.kubernetes.io/v1alpha1|g' \ -i pkg/merger/schema/generators.kustomize.aabouzaid.com_mergers.yaml + +.PHONY: go.format +go.format: + gofumpt -l -w . diff --git a/main.go b/main.go index 4971b03..ce83f87 100644 --- a/main.go +++ b/main.go @@ -3,9 +3,10 @@ package main import ( "log" - "github.com/aabouzaid/kustomize-plugin-merger/pkg/merger" "sigs.k8s.io/kustomize/kyaml/fn/framework" "sigs.k8s.io/kustomize/kyaml/kio" + + "github.com/aabouzaid/kustomize-plugin-merger/pkg/merger" ) func main() { @@ -13,7 +14,8 @@ func main() { processor := &framework.VersionedAPIProcessor{FilterProvider: framework.GVKFilterMap{ merger.ResourceKind: { merger.ResourceGroup + "/" + merger.ResourceVersion: &merger.Merger{}, - }}} + }, + }} if err := framework.Execute(processor, rlSource); err != nil { log.Fatal(err) } diff --git a/pkg/merger/doc.go b/pkg/merger/doc.go new file mode 100644 index 0000000..e673083 --- /dev/null +++ b/pkg/merger/doc.go @@ -0,0 +1,2 @@ +// Package merger is the core of a Kustomize generator plugin to merge YAML files seamlessly (schemaless merge). +package merger diff --git a/pkg/merger/fn.go b/pkg/merger/fn.go index 522a5bb..f2eda53 100644 --- a/pkg/merger/fn.go +++ b/pkg/merger/fn.go @@ -1,3 +1,4 @@ +// Methods inherited by fn/framework. package merger import ( @@ -13,6 +14,7 @@ import ( //go:embed "schema/generators.kustomize.aabouzaid.com_mergers.yaml" var mergerSchemaDefinition string +// Schema returns the OpenAPI schema definition for Merger. func (m *Merger) Schema() (*spec.Schema, error) { schema, err := framework.SchemaFromFunctionDefinition( resid.NewGvk(ResourceGroup, ResourceVersion, ResourceKind), @@ -20,6 +22,7 @@ func (m *Merger) Schema() (*spec.Schema, error) { return schema, errors.WrapPrefixf(err, "failed to parse Merger schema") } +// Default sets default values for Merger resources. func (m *Merger) Default() error { for index := range m.Spec.Resources { // Defaults input files. @@ -32,16 +35,16 @@ func (m *Merger) Default() error { return nil } -func (mg *Merger) Validate() error { - // At the moment this only validates Merger manifest against its openAPIV3Schema. +// Validate checks in Merger resource against its OpenAPI schema. +func (m *Merger) Validate() error { return nil } +// Filter performs the merging of configuration files for Merger resources. func (m *Merger) Filter(rlItems []*yaml.RNode) ([]*yaml.RNode, error) { for _, resource := range m.Spec.Resources { resource.merge(resource.Input.items) rlItems = append(rlItems, resource.Output.rlItems...) } - return rlItems, nil } diff --git a/pkg/merger/merge.go b/pkg/merger/merge.go index 0b11f11..0402839 100644 --- a/pkg/merger/merge.go +++ b/pkg/merger/merge.go @@ -1,3 +1,4 @@ +// The main logic for Merger plugin. package merger import ( @@ -10,6 +11,7 @@ import ( "sigs.k8s.io/kustomize/kyaml/yaml" ) +// setMergeStrategy sets "mergo" merging strategy, mainly for merging arrays. func (r *mergerResource) setMergeStrategy() { switch r.Merge.Strategy { case Replace: @@ -37,6 +39,7 @@ func (r *mergerResource) setInputFilesPatch() { r.Input.items = append(r.Input.items, r.Input.Files) } +// setInputFiles determines the input file sources based on the input method (Overlay or Patch). func (r *mergerResource) setInputFiles() error { switch r.Input.Method { case Overlay: @@ -47,6 +50,7 @@ func (r *mergerResource) setInputFiles() error { return nil } +// merge performs the actual merging of configuration files from resourceInputFiles sources. func (r *mergerResource) merge(rfs []resourceInputFiles) { for _, rf := range rfs { k := koanf.New(".") @@ -58,10 +62,11 @@ func (r *mergerResource) merge(rfs []resourceInputFiles) { for _, srcFile := range rf.Sources { err := k.Load(koanfFile.Provider(srcFile), koanfYaml.Parser(), koanf.WithMergeFunc(func(src, dst map[string]interface{}) error { - mergo.Merge(&dst, src, mergo.WithOverride, r.Merge.config) + if err := mergo.Merge(&dst, src, mergo.WithOverride, r.Merge.config); err != nil { + log.Fatalf("Error merging config: %v", err) + } return nil })) - if err != nil { log.Fatalf("Error loading config: %v", err) } diff --git a/pkg/merger/types.go b/pkg/merger/types.go index 7b86af6..d6d6c34 100644 --- a/pkg/merger/types.go +++ b/pkg/merger/types.go @@ -1,3 +1,6 @@ +// The types of the merger package. +// KubeBuilder markers are used to auto-generate OpenAPI schema for the plugin. +// // +groupName=generators.kustomize.aabouzaid.com // +versionName=v1alpha1 // +kubebuilder:validation:Required @@ -10,12 +13,14 @@ import ( "sigs.k8s.io/kustomize/kyaml/yaml" ) +// Merger manifest configuration. const ( ResourceGroup string = "generators.kustomize.aabouzaid.com" ResourceVersion string = "v1alpha1" ResourceKind string = "Merger" ) +// Merger manifest body. type Merger struct { metav1.TypeMeta `json:",inline"` metav1.ObjectMeta `json:"metadata"` @@ -52,6 +57,7 @@ type resourceInputFiles struct { // +kubebuilder:validation:Enum=overlay;patch type resourceInputMethod string +// Merger resource input method available options. const ( Overlay resourceInputMethod = "overlay" Patch resourceInputMethod = "patch" @@ -71,6 +77,7 @@ type resourceInput struct { // +kubebuilder:validation:Enum=append;combine;replace type resourceMergeStrategy string +// Merger resource merge strategy available options. // TODO: Support combine lists by named key. const ( Append resourceMergeStrategy = "append"