From 5d6c35d822d8fb88a8ed098ec5e2b5002d1a4091 Mon Sep 17 00:00:00 2001 From: Yuwen Ma Date: Tue, 7 Jan 2025 17:08:45 +0000 Subject: [PATCH] feat: simplify controller register step --- .../generatecontrollercommand.go | 8 +- .../generatedirectreconciler/command.go | 4 +- .../controllerbuilder/scaffold/controller.go | 80 ++++++++++++++----- .../deep-dives/4-add-controller.md | 8 +- 4 files changed, 70 insertions(+), 30 deletions(-) diff --git a/dev/tools/controllerbuilder/pkg/commands/generatecontroller/generatecontrollercommand.go b/dev/tools/controllerbuilder/pkg/commands/generatecontroller/generatecontrollercommand.go index f07119b009..93ebd6fe14 100644 --- a/dev/tools/controllerbuilder/pkg/commands/generatecontroller/generatecontrollercommand.go +++ b/dev/tools/controllerbuilder/pkg/commands/generatecontroller/generatecontrollercommand.go @@ -16,6 +16,7 @@ package generatecontroller import ( "context" + "errors" "fmt" "strings" @@ -96,5 +97,10 @@ func RunController(ctx context.Context, o *GenerateControllerOptions) error { ProtoResource: o.ProtoName, ProtoVersion: version, } - return scaffold.Scaffold(serviceName, o.ProtoName, cArgs) + err1 := scaffold.GenerateController(serviceName, o.ProtoName, cArgs) + err2 := scaffold.RegisterController(serviceName, o.ProtoName) + if err1 != nil || err2 != nil { + return errors.Join(err1, err2) + } + return nil } diff --git a/dev/tools/controllerbuilder/pkg/commands/generatedirectreconciler/command.go b/dev/tools/controllerbuilder/pkg/commands/generatedirectreconciler/command.go index 74f9a67799..975f58190d 100644 --- a/dev/tools/controllerbuilder/pkg/commands/generatedirectreconciler/command.go +++ b/dev/tools/controllerbuilder/pkg/commands/generatedirectreconciler/command.go @@ -123,7 +123,7 @@ func RunGenerateBasicReconciler(ctx context.Context, o *GenerateBasicReconcilerO OutputMapperDirectory: o.OutputMapperDirectory, } if err := generatemapper.RunGenerateMapper(ctx, mapperOps); err != nil { - return fmt.Errorf("generate types: %w", err) + return fmt.Errorf("generate mapper: %w", err) } controllerOps := &generatecontroller.GenerateControllerOptions{ GenerateOptions: o.GenerateOptions, @@ -131,7 +131,7 @@ func RunGenerateBasicReconciler(ctx context.Context, o *GenerateBasicReconcilerO ProtoName: o.ProtoName, } if err := generatecontroller.RunController(ctx, controllerOps); err != nil { - return fmt.Errorf("generate types: %w", err) + return fmt.Errorf("generate controller: %w", err) } return nil } diff --git a/dev/tools/controllerbuilder/scaffold/controller.go b/dev/tools/controllerbuilder/scaffold/controller.go index 401f4e1514..3d7abb9792 100644 --- a/dev/tools/controllerbuilder/scaffold/controller.go +++ b/dev/tools/controllerbuilder/scaffold/controller.go @@ -18,14 +18,18 @@ import ( "bytes" "errors" "fmt" - "io/fs" + "go/format" + "go/parser" + "go/token" "os" "path/filepath" + "runtime/debug" "strings" "text/template" ccTemplate "github.com/GoogleCloudPlatform/k8s-config-connector/dev/tools/controllerbuilder/template/controller" "github.com/fatih/color" + "golang.org/x/tools/go/ast/astutil" "golang.org/x/tools/imports" ) @@ -38,14 +42,47 @@ var funcMap = template.FuncMap{ "ToLower": strings.ToLower, } -func Scaffold(service, kind string, cArgs *ccTemplate.ControllerArgs) error { - if err := generateController(service, kind, cArgs); err != nil { +func RegisterController(service, kind string) error { + // Read register file + directControllerPkgPath, err := buildDirectControllerPath() + if err != nil { + return nil + } + registerFilePath := filepath.Join(directControllerPkgPath, "register", "register.go") + fset := token.NewFileSet() + f, err := parser.ParseFile(fset, registerFilePath, nil, parser.ParseComments) + if err != nil { return err } + + // Get main model name + bi, ok := debug.ReadBuildInfo() + if !ok { + return fmt.Errorf("could not read build info") + } + modelPath := strings.TrimSuffix(bi.Main.Path, currRelPath) + + importPath := filepath.Join(modelPath, directControllerRelPath, service) + added := astutil.AddNamedImport(fset, f, "_", importPath) + if !added { + fmt.Printf("skip registering controller %s\n", service) + return nil + } + + out := &bytes.Buffer{} + err = format.Node(out, fset, f) + if err != nil { + return fmt.Errorf("error formatting code: %w", err) + } + + if err := FormatImports(registerFilePath, out.Bytes()); err != nil { + return err + } + color.HiGreen("New controller %s has been registered.\n", kind) return nil } -func generateController(service, kind string, cArgs *ccTemplate.ControllerArgs) error { +func GenerateController(service, kind string, cArgs *ccTemplate.ControllerArgs) error { tmpl, err := template.New(cArgs.Kind).Funcs(funcMap).Parse(ccTemplate.ControllerTemplate) if err != nil { return fmt.Errorf("parse controller template: %w", err) @@ -60,6 +97,12 @@ func generateController(service, kind string, cArgs *ccTemplate.ControllerArgs) if err != nil { return err } + if _, err := os.Stat(controllerFilePath); err == nil { + fmt.Printf("file %s already exists, skipping\n", controllerFilePath) + return nil + } else if !errors.Is(err, os.ErrNotExist) { + return fmt.Errorf("unexpected controller file: %w", err) + } // Write the generated controller.go to pkg/controller/direct//_controller.go if err := WriteToFile(controllerFilePath, controllerOutput.Bytes()); err != nil { @@ -69,11 +112,11 @@ func generateController(service, kind string, cArgs *ccTemplate.ControllerArgs) if err := FormatImports(controllerFilePath, controllerOutput.Bytes()); err != nil { return err } - color.HiGreen("New controller %s has been generated. \nEnjoy it!\n", kind) + color.HiGreen("New controller %s has been generated.", kind) return nil } -func buildResourcePath(service, filename string) (string, error) { +func buildDirectControllerPath() (string, error) { pwd, err := os.Getwd() if err != nil { return "", fmt.Errorf("get current working directory: %w", err) @@ -83,24 +126,21 @@ func buildResourcePath(service, filename string) (string, error) { return "", fmt.Errorf("get absolute path %s: %w", pwd, err) } seg := strings.Split(abs, currRelPath) - controllerDir := filepath.Join(seg[0], directControllerRelPath, service) + return filepath.Join(seg[0], directControllerRelPath), nil +} + +func buildControllerPath(service, protoResource string) (string, error) { + filename := strings.ToLower(protoResource) + "_controller.go" + directControllerPkgPath, err := buildDirectControllerPath() + if err != nil { + return "", nil + } + controllerDir := filepath.Join(directControllerPkgPath, service) err = os.MkdirAll(controllerDir, os.ModePerm) if err != nil { return "", fmt.Errorf("create controller directory %s: %w", controllerDir, err) } - resourceFilePath := filepath.Join(controllerDir, filename) - if _, err = os.Stat(resourceFilePath); err != nil { - if !errors.Is(err, fs.ErrNotExist) { - return "", fmt.Errorf("could not stat path %s: %w", resourceFilePath, err) - } - // otherwise create the file - return resourceFilePath, nil - } - return "", fmt.Errorf("file %s already exist", resourceFilePath) -} - -func buildControllerPath(service, protoResource string) (string, error) { - return buildResourcePath(service, strings.ToLower(protoResource)+"_controller.go") + return filepath.Join(controllerDir, filename), nil } func FormatImports(path string, out []byte) error { diff --git a/docs/develop-resources/deep-dives/4-add-controller.md b/docs/develop-resources/deep-dives/4-add-controller.md index 7ec6a8e5bc..6f4d1e7daa 100644 --- a/docs/develop-resources/deep-dives/4-add-controller.md +++ b/docs/develop-resources/deep-dives/4-add-controller.md @@ -22,13 +22,7 @@ if there is no previous reference method, You may need to add a new` Resolve