diff --git a/cmd/controller-gen/main.go b/cmd/controller-gen/main.go index d224edd1a..74c29d21d 100644 --- a/cmd/controller-gen/main.go +++ b/cmd/controller-gen/main.go @@ -114,6 +114,8 @@ Usage: f.StringVar(&g.Domain, "domain", "", "domain of the resources, will try to fetch it from PROJECT file if not specified") f.StringVar(&g.Namespace, "namespace", "", "CRD namespace, treat it as cluster scoped if not set") f.BoolVar(&g.SkipMapValidation, "skip-map-validation", true, "if set to true, skip generating OpenAPI validation schema for map type in CRD.") + f.StringVar(&g.APIsPath, "apis-path", "pkg/apis", "the path to search for apis relative to the current directory") + f.StringVar(&g.APIsPkg, "apis-pkg", "", "the absolute Go pkg name for current project's api pkg.") return cmd } diff --git a/cmd/crd/cmd/generate.go b/cmd/crd/cmd/generate.go index ed4b90136..32c9ade73 100644 --- a/cmd/crd/cmd/generate.go +++ b/cmd/crd/cmd/generate.go @@ -66,5 +66,7 @@ func GeneratorForFlags(f *flag.FlagSet) *crdgenerator.Generator { // TODO: Do we need this? Is there a possibility that a crd is namespace scoped? f.StringVar(&g.Namespace, "namespace", "", "CRD namespace, treat it as root scoped if not set") f.BoolVar(&g.SkipMapValidation, "skip-map-validation", true, "if set to true, skip generating validation schema for map type in CRD.") + f.StringVar(&g.APIsPath, "apis-path", "pkg/apis", "the path to search for apis relative to the current directory") + f.StringVar(&g.APIsPkg, "apis-pkg", "", "the absolute Go pkg name for current project's api pkg.") return g } diff --git a/pkg/crd/generator/generator.go b/pkg/crd/generator/generator.go index 512311873..dfbf15278 100644 --- a/pkg/crd/generator/generator.go +++ b/pkg/crd/generator/generator.go @@ -48,6 +48,10 @@ type Generator struct { // apisPkg is the absolute Go pkg name for current project's 'pkg/apis' pkg. // This is needed to determine if a Type belongs to the project or it is a referred Type. apisPkg string + + // APIsPath and APIsPkg allow customized generation for Go types existing under directories other than pkg/apis + APIsPath string + APIsPkg string } // ValidateAndInitFields validate and init generator fields. @@ -80,13 +84,7 @@ func (c *Generator) ValidateAndInitFields() error { c.Domain = crdutil.GetDomainFromProject(c.RootPath) } - // Validate apis directory exists under working path - apisPath := path.Join(c.RootPath, "pkg/apis") - if _, err := os.Stat(apisPath); err != nil { - return fmt.Errorf("error validating apis path %s: %v", apisPath, err) - } - - c.apisPkg, err = crdutil.DirToGoPkg(apisPath) + err = c.setAPIsPkg() if err != nil { return err } @@ -112,7 +110,7 @@ func (c *Generator) Do() error { return fmt.Errorf("failed switching working dir: %v", err) } - if err := b.AddDirRecursive("./pkg/apis"); err != nil { + if err := b.AddDirRecursive("./" + c.APIsPath); err != nil { return fmt.Errorf("failed making a parser: %v", err) } ctx, err := parse.NewContext(b) @@ -185,3 +183,25 @@ func (c *Generator) getCrds(p *parse.APIs) map[string][]byte { func (c *Generator) belongsToAPIsPkg(t *types.Type) bool { return strings.HasPrefix(t.Name.Package, c.apisPkg) } + +func (c *Generator) setAPIsPkg() error { + var err error + if c.APIsPath == "" { + c.APIsPath = "pkg/apis" + } + + c.apisPkg = c.APIsPkg + if c.apisPkg == "" { + // Validate apis directory exists under working path + apisPath := path.Join(c.RootPath, c.APIsPath) + if _, err := os.Stat(apisPath); err != nil { + return fmt.Errorf("error validating apis path %s: %v", apisPath, err) + } + + c.apisPkg, err = crdutil.DirToGoPkg(apisPath) + if err != nil { + return err + } + } + return nil +}