github.com/crossplane/upjet@v1.3.0/pkg/pipeline/setup.go (about) 1 // SPDX-FileCopyrightText: 2023 The Crossplane Authors <https://crossplane.io> 2 // 3 // SPDX-License-Identifier: Apache-2.0 4 5 package pipeline 6 7 import ( 8 "fmt" 9 "log" 10 "os" 11 "path/filepath" 12 "sort" 13 "text/template" 14 15 "github.com/muvaf/typewriter/pkg/wrapper" 16 "github.com/pkg/errors" 17 18 "github.com/crossplane/upjet/pkg/config" 19 "github.com/crossplane/upjet/pkg/pipeline/templates" 20 ) 21 22 // NewProviderGenerator returns a new ProviderGenerator. 23 func NewProviderGenerator(rootDir, modulePath string) *ProviderGenerator { 24 return &ProviderGenerator{ 25 ProviderPath: filepath.Join(rootDir, "cmd", "provider"), 26 LocalDirectoryPath: filepath.Join(rootDir, "internal", "controller"), 27 LicenseHeaderPath: filepath.Join(rootDir, "hack", "boilerplate.go.txt"), 28 ModulePath: modulePath, 29 } 30 } 31 32 // ProviderGenerator generates controller setup file. 33 type ProviderGenerator struct { 34 ProviderPath string 35 LocalDirectoryPath string 36 LicenseHeaderPath string 37 ModulePath string 38 } 39 40 // Generate writes the setup file and the corresponding provider main file 41 // using the given list of version packages. 42 func (sg *ProviderGenerator) Generate(versionPkgMap map[string][]string, mainTemplate string) error { 43 var t *template.Template 44 if len(mainTemplate) != 0 { 45 tmpl, err := template.New("main").Parse(mainTemplate) 46 if err != nil { 47 return errors.Wrap(err, "failed to parse the provider main program template") 48 } 49 t = tmpl 50 } 51 if t == nil { 52 return errors.Wrap(sg.generate("", versionPkgMap[config.PackageNameMonolith]), "failed to generate the controller setup file") 53 } 54 for g, versionPkgList := range versionPkgMap { 55 if err := sg.generate(g, versionPkgList); err != nil { 56 return errors.Wrapf(err, "failed to generate the controller setup file for group: %s", g) 57 } 58 if err := generateProviderMain(sg.ProviderPath, g, t); err != nil { 59 return errors.Wrapf(err, "failed to write main program for group: %s", g) 60 } 61 } 62 return nil 63 } 64 65 func generateProviderMain(providerPath, group string, t *template.Template) error { 66 f := filepath.Join(providerPath, group) 67 if err := os.MkdirAll(f, 0750); err != nil { 68 return errors.Wrapf(err, "failed to mkdir provider main program path: %s", f) 69 } 70 m, err := os.OpenFile(filepath.Join(filepath.Clean(f), "zz_main.go"), os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0600) 71 if err != nil { 72 return errors.Wrap(err, "failed to open provider main program file") 73 } 74 defer func() { 75 if err := m.Close(); err != nil { 76 log.Fatalf("Failed to close the templated main %q: %s", f, err.Error()) 77 } 78 }() 79 if err := t.Execute(m, map[string]any{ 80 "Group": group, 81 }); err != nil { 82 return errors.Wrap(err, "failed to execute provider main program template") 83 } 84 return nil 85 } 86 87 func (sg *ProviderGenerator) generate(group string, versionPkgList []string) error { 88 setupFile := wrapper.NewFile(filepath.Join(sg.ModulePath, "apis"), "apis", templates.SetupTemplate, 89 wrapper.WithGenStatement(GenStatement), 90 wrapper.WithHeaderPath(sg.LicenseHeaderPath), 91 ) 92 sort.Strings(versionPkgList) 93 aliases := make([]string, len(versionPkgList)) 94 for i, pkgPath := range versionPkgList { 95 aliases[i] = setupFile.Imports.UsePackage(pkgPath) 96 } 97 g := "" 98 if len(group) != 0 { 99 g = "_" + group 100 } 101 vars := map[string]any{ 102 "Aliases": aliases, 103 "Group": g, 104 } 105 filePath := "" 106 if len(group) == 0 { 107 filePath = filepath.Join(sg.LocalDirectoryPath, "zz_setup.go") 108 } else { 109 filePath = filepath.Join(sg.LocalDirectoryPath, fmt.Sprintf("zz_%s_setup.go", group)) 110 } 111 return errors.Wrap(setupFile.Write(filePath, vars, os.ModePerm), "cannot write setup file") 112 }