Skip to content

Commit

Permalink
tool: unify --resource flag format across commands
Browse files Browse the repository at this point in the history
Update "generate-controller" and "generate-direct-reconciler" commands to use the same
"--resource Kind:ProtoName" flag format as other commands for consistency in the CLI interface.
  • Loading branch information
jingyih committed Dec 12, 2024
1 parent 4db732a commit 275d08a
Show file tree
Hide file tree
Showing 6 changed files with 98 additions and 62 deletions.
3 changes: 1 addition & 2 deletions dev/tools/controllerbuilder/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,7 @@ go run . generate-mapper \
# To scaffold generate the SecretManagerSecretVersion controller
go run . generate-direct-reconciler \
--kind SecretManagerSecretVersion \
--proto-resource SecretVersion \
--resource SecretManagerSecretVersion:SecretVersion \
--api-version "secretmanager.cnrm.cloud.google.com/v1beta1" \
--service "google.cloud.secretmanager.v1"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,13 +29,11 @@ import (
type GenerateControllerOptions struct {
*options.GenerateOptions

Kind string
ProtoName string
Resource options.Resource
}

func (o *GenerateControllerOptions) BindFlags(cmd *cobra.Command) {
cmd.Flags().StringVarP(&o.ProtoName, "proto-resource", "p", "", "the GCP resource proto name. It should match the name in the proto apis. i.e. For resource google.storage.v1.bucket, the `--proto-resource` should be `Bucket`.")
cmd.Flags().StringVarP(&o.Kind, "kind", "k", "", "the KCC resource Kind. requires `--proto-resource`.")
cmd.Flags().Var(&o.Resource, "resource", "the KRM Kind and the equivalent proto resource separated with a colon. e.g. for resource google.storage.v1.Bucket, the flag should be `StorageBucket:Bucket`.")
}

func BuildCommand(baseOptions *options.GenerateOptions) *cobra.Command {
Expand All @@ -47,11 +45,14 @@ func BuildCommand(baseOptions *options.GenerateOptions) *cobra.Command {
Use: "generate-controller",
Short: "generate the direct controller",
PreRunE: func(cmd *cobra.Command, args []string) error {
if opt.Kind == "" {
return fmt.Errorf("--kind is required")
if opt.Resource == (options.Resource{}) {
return fmt.Errorf("--resource flag is required")
}
if opt.ProtoName == "" {
return fmt.Errorf("--proto-resource is required")
if opt.Resource.Kind == "" {
return fmt.Errorf("need to specify KRM Kind in --resource")
}
if opt.Resource.ProtoName == "" {
return fmt.Errorf("need to specify proto resource name in --resource")
}

if baseOptions.APIVersion == "" {
Expand Down Expand Up @@ -92,9 +93,9 @@ func RunController(ctx context.Context, o *GenerateControllerOptions) error {
cArgs := &cctemplate.ControllerArgs{
KCCService: serviceName,
KCCVersion: gv.Version,
Kind: o.Kind,
ProtoResource: o.ProtoName,
Kind: o.Resource.Kind,
ProtoResource: o.Resource.ProtoName,
ProtoVersion: version,
}
return scaffold.Scaffold(serviceName, o.ProtoName, cArgs)
return scaffold.Scaffold(serviceName, o.Resource.ProtoName, cArgs)
}
Original file line number Diff line number Diff line change
Expand Up @@ -29,19 +29,15 @@ import (

type GenerateBasicReconcilerOptions struct {
*options.GenerateOptions
Kind string
ProtoName string
// OutputAPIDirectory string
Resource options.Resource

APIGoPackagePath string
APIDirectory string
OutputMapperDirectory string
}

func (o *GenerateBasicReconcilerOptions) BindFlags(cmd *cobra.Command) {
cmd.Flags().StringVarP(&o.ProtoName, "proto-resource", "p", "", "the GCP resource proto name. It should match the name in the proto apis. i.e. For resource google.storage.v1.bucket, the `--proto-resource` should be `bucket`. If `--kind` is not given, the `--proto-resource` value will also be used as the kind name with a capital letter `Storage`.")
cmd.Flags().StringVarP(&o.Kind, "kind", "k", "", "the KCC resource Kind. requires `--proto-resource`.")
// cmd.Flags().StringVar(&o.OutputAPIDirectory, "output-api", o.OutputAPIDirectory, "base directory for writing APIs")
cmd.Flags().Var(&o.Resource, "resource", "the KRM Kind and the equivalent proto resource separated with a colon. e.g. for resource google.storage.v1.Bucket, the flag should be `StorageBucket:Bucket`")
cmd.Flags().StringVar(&o.APIGoPackagePath, "api-go-package-path", o.APIGoPackagePath, "package path")
cmd.Flags().StringVar(&o.APIDirectory, "api-dir", o.APIDirectory, "base directory for reading APIs")
cmd.Flags().StringVar(&o.OutputMapperDirectory, "output-dir", o.OutputMapperDirectory, "base directory for writing mappers")
Expand Down Expand Up @@ -73,12 +69,16 @@ func BuildCommand(baseOptions *options.GenerateOptions) *cobra.Command {
Use: "generate-direct-reconciler",
Short: "[ALPHA] generate a basic direct reconciler that is up and run",
PreRunE: func(cmd *cobra.Command, args []string) error {
if opt.Kind == "" {
return fmt.Errorf("--kind is required")
if opt.Resource == (options.Resource{}) {
return fmt.Errorf("--resource flag is required")
}
if opt.ProtoName == "" {
return fmt.Errorf("--proto-resource is required")
if opt.Resource.Kind == "" {
return fmt.Errorf("need to specify KRM Kind in --resource")
}
if opt.Resource.ProtoName == "" {
return fmt.Errorf("need to specify proto resource name in --resource")
}

if baseOptions.APIVersion == "" {
return fmt.Errorf("--api-version is required")
}
Expand Down Expand Up @@ -109,9 +109,7 @@ func RunGenerateBasicReconciler(ctx context.Context, o *GenerateBasicReconcilerO
crdOps := &generatetypes.GenerateCRDOptions{
GenerateOptions: o.GenerateOptions,
OutputAPIDirectory: o.APIDirectory,
Resources: generatetypes.ResourceList{
generatetypes.Resource{Kind: o.Kind, ProtoName: o.ProtoName},
},
Resources: options.ResourceList{o.Resource},
}
if err := generatetypes.RunGenerateCRD(ctx, crdOps); err != nil {
return fmt.Errorf("generate types: %w", err)
Expand All @@ -127,8 +125,7 @@ func RunGenerateBasicReconciler(ctx context.Context, o *GenerateBasicReconcilerO
}
controllerOps := &generatecontroller.GenerateControllerOptions{
GenerateOptions: o.GenerateOptions,
Kind: o.Kind,
ProtoName: o.ProtoName,
Resource: o.Resource,
}
if err := generatecontroller.RunController(ctx, controllerOps); err != nil {
return fmt.Errorf("generate types: %w", err)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@ import (
"k8s.io/klog/v2"

"github.com/spf13/cobra"
"github.com/spf13/pflag"
)

type GenerateCRDOptions struct {
Expand All @@ -38,38 +37,7 @@ type GenerateCRDOptions struct {
OutputAPIDirectory string
SkipScaffoldFiles bool

Resources ResourceList
}

type Resource struct {
Kind string
ProtoName string
}

type ResourceList []Resource

var _ pflag.Value = &ResourceList{}

func (r *ResourceList) Type() string { return "resources" }

func (r *ResourceList) String() string {
var sb strings.Builder
for _, res := range *r {
fmt.Fprintf(&sb, "%s:%s", res.Kind, res.ProtoName)
}
return sb.String()
}

func (r *ResourceList) Set(s string) error {
tokens := strings.Split(s, ":")
if len(tokens) != 2 || tokens[0] == "" || tokens[1] == "" {
return fmt.Errorf("expected [KRMKind]:[ProtoResourceName], got %q", s)
}
*r = append(*r, Resource{
Kind: tokens[0],
ProtoName: tokens[1],
})
return nil
Resources options.ResourceList
}

func (o *GenerateCRDOptions) InitDefaults() error {
Expand Down
71 changes: 71 additions & 0 deletions dev/tools/controllerbuilder/pkg/options/resource.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
// Copyright 2024 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package options

import (
"fmt"
"strings"

"github.com/spf13/pflag"
)

type Resource struct {
Kind string
ProtoName string
}

var _ pflag.Value = &Resource{}

func (r *Resource) Type() string { return "resource" }

func (r *Resource) String() string {
return fmt.Sprintf("%s:%s", r.Kind, r.ProtoName)
}

func (r *Resource) Set(s string) error {
tokens := strings.Split(s, ":")
if len(tokens) != 2 || tokens[0] == "" || tokens[1] == "" {
return fmt.Errorf("expected [KRMKind]:[ProtoResourceName], got %q", s)
}
r.Kind = tokens[0]
r.ProtoName = tokens[1]
return nil
}

type ResourceList []Resource

var _ pflag.Value = &ResourceList{}

func (r *ResourceList) Type() string { return "resources" }

func (r *ResourceList) String() string {
var sb strings.Builder
for _, res := range *r {
fmt.Fprintf(&sb, "%s:%s", res.Kind, res.ProtoName)
}
return sb.String()
}

func (r *ResourceList) Set(s string) error {
tokens := strings.Split(s, ":")
if len(tokens) != 2 || tokens[0] == "" || tokens[1] == "" {
return fmt.Errorf("expected [KRMKind]:[ProtoResourceName], got %q", s)
}
*r = append(*r, Resource{
Kind: tokens[0],
ProtoName: tokens[1],
})
return nil
}
2 changes: 1 addition & 1 deletion docs/develop-resources/deep-dives/4-add-controller.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ Run the following command to generate a controller template

```
cd dev/tools/controllerbuilder
go run main.go generate-controller --service <YOUR_SERVICE> --api-version <VERSION> --kind <YOUR_RESOURCE> --proto-resource <PROTO_RESOURCE>
go run main.go generate-controller --service <YOUR_SERVICE> --api-version <VERSION> --resource <YOUR_RESOURCE>:<PROTO_RESOURCE>
```

Fix the generated code to make your SciFi running!
Expand Down

0 comments on commit 275d08a

Please sign in to comment.