Skip to content

Commit

Permalink
Generate provider subpackages
Browse files Browse the repository at this point in the history
Signed-off-by: Alper Rifat Ulucinar <[email protected]>
  • Loading branch information
ulucinar committed Apr 25, 2023
1 parent 549776a commit d71b091
Show file tree
Hide file tree
Showing 4 changed files with 65 additions and 8 deletions.
10 changes: 10 additions & 0 deletions pkg/config/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,10 @@ type Provider struct {
// can add "aws_waf.*" to the list.
SkipList []string

// MainTemplate is the template string to be used to render the
// provider subpackage main program.
MainTemplate string

// skippedResourceNames is a list of Terraform resource names
// available in the Terraform provider schema, but
// not in the include list or in the skip list, meaning that
Expand Down Expand Up @@ -183,6 +187,12 @@ func WithFeaturesPackage(s string) ProviderOption {
}
}

func WithMainTemplate(template string) ProviderOption {
return func(p *Provider) {
p.MainTemplate = template
}
}

// NewProvider builds and returns a new Provider from provider
// tfjson schema, that is generated using Terraform CLI with:
// `terraform providers schema --json`
Expand Down
15 changes: 11 additions & 4 deletions pkg/pipeline/run.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,9 +56,14 @@ func Run(pc *config.Provider, rootDir string) { // nolint:gocyclo
apiVersionPkgList = append(apiVersionPkgList, filepath.Join(pc.ModulePath, p))
}
// Add ProviderConfig controller package to the list of controller packages.
controllerPkgList := make([]string, 0)
controllerPkgMap := make(map[string][]string)
for _, p := range pc.BasePackages.Controller {
controllerPkgList = append(controllerPkgList, filepath.Join(pc.ModulePath, p))
tokens := strings.Split(p, "/")
group := tokens[len(tokens)-1]
if group == "providerconfig" {
group = pc.ShortName
}
controllerPkgMap[group] = append(controllerPkgMap[group], filepath.Join(pc.ModulePath, p))
}
count := 0
for group, versions := range resourcesGroups {
Expand Down Expand Up @@ -87,7 +92,8 @@ func Run(pc *config.Provider, rootDir string) { // nolint:gocyclo
if err != nil {
panic(errors.Wrapf(err, "cannot generate controller for resource %s", name))
}
controllerPkgList = append(controllerPkgList, ctrlPkgPath)
sGroup := strings.Split(group, ".")[0]
controllerPkgMap[sGroup] = append(controllerPkgMap[sGroup], ctrlPkgPath)
if err := exampleGen.Generate(group, version, resources[name]); err != nil {
panic(errors.Wrapf(err, "cannot generate example manifest for resource %s", name))
}
Expand All @@ -112,7 +118,8 @@ func Run(pc *config.Provider, rootDir string) { // nolint:gocyclo
if err := NewRegisterGenerator(rootDir, pc.ModulePath).Generate(apiVersionPkgList); err != nil {
panic(errors.Wrap(err, "cannot generate register file"))
}
if err := NewSetupGenerator(rootDir, pc.ModulePath).Generate(controllerPkgList); err != nil {
// TODO: make a separate generator for the provider main program
if err := NewSetupGenerator(rootDir, pc.ModulePath).Generate(controllerPkgMap, pc.MainTemplate); err != nil {
panic(errors.Wrap(err, "cannot generate setup file"))
}

Expand Down
44 changes: 42 additions & 2 deletions pkg/pipeline/setup.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,11 @@ Copyright 2021 Upbound Inc.
package pipeline

import (
"fmt"
"os"
"path/filepath"
"sort"
"text/template"

"github.com/muvaf/typewriter/pkg/wrapper"
"github.com/pkg/errors"
Expand All @@ -18,6 +20,7 @@ import (
// NewSetupGenerator returns a new SetupGenerator.
func NewSetupGenerator(rootDir, modulePath string) *SetupGenerator {
return &SetupGenerator{
ProviderPath: filepath.Join(rootDir, "cmd", "provider"),
LocalDirectoryPath: filepath.Join(rootDir, "internal", "controller"),
LicenseHeaderPath: filepath.Join(rootDir, "hack", "boilerplate.go.txt"),
ModulePath: modulePath,
Expand All @@ -26,14 +29,50 @@ func NewSetupGenerator(rootDir, modulePath string) *SetupGenerator {

// SetupGenerator generates controller setup file.
type SetupGenerator struct {
ProviderPath string
LocalDirectoryPath string
LicenseHeaderPath string
ModulePath string
}

// Generate writes the setup file with the content produced using given
// list of version packages.
func (sg *SetupGenerator) Generate(versionPkgList []string) error {

func (sg *SetupGenerator) Generate(versionPkgMap map[string][]string, mainTemplate string) error {
t, err := template.New("main").Parse(mainTemplate)
if err != nil {
return errors.Wrap(err, "failed to parse provider main program template")
}
for g, versionPkgList := range versionPkgMap {
if err := sg.generate(g, versionPkgList); err != nil {
return errors.Wrapf(err, "failed to generate controller setup file for group: %s", g)
}
if err := writeMainProgram(sg.ProviderPath, g, t); err != nil {
return errors.Wrapf(err, "failed to write main program for group: %s", g)
}
}
return nil
}

func writeMainProgram(providerPath, group string, t *template.Template) error {
f := filepath.Join(providerPath, group)
if err := os.MkdirAll(f, 0755); err != nil {
return errors.Wrapf(err, "failed to mkdir provider main program path: %s", f)
}
m, err := os.OpenFile(filepath.Join(f, "main.go"), os.O_WRONLY|os.O_CREATE, 0755)
if err != nil {
return errors.Wrap(err, "failed to open provider main program file")
}
defer m.Close()
if err := t.Execute(m, map[string]any{
"Group": group,
}); err != nil {
return errors.Wrap(err, "failed to execute provider main program template")
}
return nil
}

func (sg *SetupGenerator) generate(group string, versionPkgList []string) error {
setupFile := wrapper.NewFile(filepath.Join(sg.ModulePath, "apis"), "apis", templates.SetupTemplate,
wrapper.WithGenStatement(GenStatement),
wrapper.WithHeaderPath(sg.LicenseHeaderPath),
Expand All @@ -45,7 +84,8 @@ func (sg *SetupGenerator) Generate(versionPkgList []string) error {
}
vars := map[string]any{
"Aliases": aliases,
"Group": group,
}
filePath := filepath.Join(sg.LocalDirectoryPath, "zz_setup.go")
filePath := filepath.Join(sg.LocalDirectoryPath, fmt.Sprintf("zz_%s_setup.go", group))
return errors.Wrap(setupFile.Write(filePath, vars, os.ModePerm), "cannot write setup file")
}
4 changes: 2 additions & 2 deletions pkg/pipeline/templates/setup.go.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,9 @@ import (
{{ .Imports }}
)

// Setup creates all controllers with the supplied logger and adds them to
// Setup_{{ .Group }} creates all controllers with the supplied logger and adds them to
// the supplied manager.
func Setup(mgr ctrl.Manager, o controller.Options) error {
func Setup_{{ .Group }}(mgr ctrl.Manager, o controller.Options) error {
for _, setup := range []func(ctrl.Manager, controller.Options) error{
{{- range $alias := .Aliases }}
{{ $alias }}Setup,
Expand Down

0 comments on commit d71b091

Please sign in to comment.