package kustomize import ( "bytes" "errors" "fmt" "html/template" "os" "path/filepath" "git.badhouseplants.net/allanger/shoebill/internal/utils/githelper" "github.com/sirupsen/logrus" kustomize_types "sigs.k8s.io/kustomize/api/types" "sigs.k8s.io/yaml" ) type Kusmtomize struct { Files []string ConfigMaps []string Secrets []string } func (k *Kusmtomize) PopulateResources(path string) error { // Main sources files, err := os.ReadDir(fmt.Sprintf("%s/src", path)) if err != nil { return err } for _, file := range files { if file.Name() != ".gitkeep" && !file.IsDir() { k.Files = append(k.Files, fmt.Sprintf("src/%s", file.Name())) } } // Values files, err = os.ReadDir(fmt.Sprintf("%s/src/values", path)) if err != nil { return err } for _, file := range files { k.ConfigMaps = append(k.ConfigMaps, fmt.Sprintf("src/values/%s", file.Name())) } // Secrets files, err = os.ReadDir(fmt.Sprintf("%s/src/secrets", path)) if err != nil { return err } for _, file := range files { k.Secrets = append(k.Secrets, fmt.Sprintf("src/secrets/%s", file.Name())) } return nil } func (k *Kusmtomize) SecGeneratorCreate(path string) error { logrus.Info("preparing the secret generator file") genFileTmpl := `--- apiVersion: viaduct.ai/v1 kind: ksops metadata: name: shoebill-secret-gen files: {{- range $val := . }} - {{ $val }} {{- end }} ` destFileName := fmt.Sprintf("%s/sec-generator.yaml", path) t := template.Must(template.New("tmpl").Parse(genFileTmpl)) var genFileData bytes.Buffer t.Execute(&genFileData, k.Secrets) var genFile *os.File if _, err := os.Stat(destFileName); err == nil { genFile, err := os.Open(destFileName) if err != nil { return err } defer genFile.Close() } else if errors.Is(err, os.ErrNotExist) { genFile, err = os.Create(destFileName) if err != nil { return nil } defer genFile.Close() } else { return err } if err := os.WriteFile(destFileName, genFileData.Bytes(), os.ModeExclusive); err != nil { return nil } return nil } func (k *Kusmtomize) CmGeneratorFromFiles() []kustomize_types.ConfigMapArgs { cmGens := []kustomize_types.ConfigMapArgs{} for _, cm := range k.ConfigMaps { cmName := filepath.Base(cm) cmGen := &kustomize_types.ConfigMapArgs{ GeneratorArgs: kustomize_types.GeneratorArgs{ Namespace: "flux-system", Name: cmName, KvPairSources: kustomize_types.KvPairSources{ FileSources: []string{cm}, }, }, } cmGens = append(cmGens, *cmGen) } return cmGens } func Generate(path string, gh githelper.Githelper) error { kustomize := &Kusmtomize{} if err := kustomize.PopulateResources(path); err != nil { return err } kustomization := kustomize_types.Kustomization{ TypeMeta: kustomize_types.TypeMeta{ Kind: kustomize_types.KustomizationKind, APIVersion: kustomize_types.KustomizationVersion, }, MetaData: &kustomize_types.ObjectMeta{ Name: "helm-root", Namespace: "flux-system", }, Resources: kustomize.Files, GeneratorOptions: &kustomize_types.GeneratorOptions{ DisableNameSuffixHash: true, }, ConfigMapGenerator: kustomize.CmGeneratorFromFiles(), } if len(kustomize.Secrets) > 0 { kustomization.Generators = []string{"sec-generator.yaml"} if err := kustomize.SecGeneratorCreate(path); err != nil { return err } } else { if err := os.RemoveAll(fmt.Sprintf("%s/sec-generator.yaml", path)); err != nil { return err } } manifest, err := yaml.Marshal(kustomization) if err != nil { return err } dstFilePath := path + "/kustomization.yaml" var dstFile *os.File if _, err = os.Stat(dstFilePath); err == nil { dstFile, err = os.Open(dstFilePath) if err != nil { return err } defer dstFile.Close() } else if errors.Is(err, os.ErrNotExist) { dstFile, err = os.Create(dstFilePath) if err != nil { return nil } defer dstFile.Close() } else { return err } if err := os.WriteFile(dstFilePath, manifest, os.ModeExclusive); err != nil { return nil } if err := gh.AddAllAndCommit(path, "Update the root kustomization"); err != nil { return err } return nil }