diff --git a/pkg/cli/cli.go b/pkg/cli/cli.go index f5f71b70c26..ace342be7a8 100644 --- a/pkg/cli/cli.go +++ b/pkg/cli/cli.go @@ -40,6 +40,7 @@ const ( pluginsFlag = "plugins" projectVersionFlag = "project-version" + projectFileFlag = "project-file" ) // CLI is the command line utility that is used to scaffold kubebuilder project files. @@ -73,6 +74,8 @@ type CLI struct { pluginKeys []string // Project version to scaffold. projectVersion config.Version + // Project file path to use instead of default PROJECT file. + projectFile string // A filtered set of plugins that should be used by command constructors. resolvedPlugins []plugin.Plugin @@ -211,6 +214,12 @@ func (c *CLI) getInfoFromConfigFile() error { // Read the project configuration file cfg := yamlstore.New(c.fs) + // Determine which project file to use. + projectPath := yamlstore.DefaultPath + if c.projectFile != "" { + projectPath = c.projectFile + } + // Workaround for https://github.com/kubernetes-sigs/kubebuilder/issues/4433 // // This allows the `kubebuilder alpha generate` command to work with old projects @@ -222,12 +231,12 @@ func (c *CLI) getInfoFromConfigFile() error { if isAlphaGenerateCommand(os.Args[1:]) { // Patch raw file bytes before unmarshalling - if err := patchProjectFileInMemoryIfNeeded(c.fs.FS, yamlstore.DefaultPath); err != nil { + if err := patchProjectFileInMemoryIfNeeded(c.fs.FS, projectPath); err != nil { return err } } - if err := cfg.Load(); err != nil { + if err := cfg.LoadFrom(projectPath); err != nil { return fmt.Errorf("error loading configuration: %w", err) } @@ -418,6 +427,13 @@ func (c *CLI) getInfoFromFlags(hasConfigFile bool) error { } } + // Extract the project-file flag if provided. + if projectFile, err := fs.GetString(projectFileFlag); err != nil { + return fmt.Errorf("invalid flag %q: %w", projectFileFlag, err) + } else if projectFile != "" { + c.projectFile = projectFile + } + return nil } diff --git a/pkg/cli/cmd_helpers.go b/pkg/cli/cmd_helpers.go index b6af5ef4dc9..8c6af599576 100644 --- a/pkg/cli/cmd_helpers.go +++ b/pkg/cli/cmd_helpers.go @@ -157,6 +157,7 @@ func (c *CLI) applySubcommandHooks( store: yamlstore.New(c.fs), subcommands: subcommands, errorMessage: errorMessage, + projectFile: c.projectFile, projectVersion: c.projectVersion, pluginChain: pluginChain, cliVersion: c.cliVersion, @@ -296,6 +297,8 @@ type executionHooksFactory struct { subcommands []keySubcommandTuple // errorMessage is prepended to returned errors. errorMessage string + // projectFile is the path to the project configuration file (empty means use default: PROJECT). + projectFile string // projectVersion is the project version that will be used to create new project configurations. // It is only used for initialization. projectVersion config.Version @@ -407,7 +410,13 @@ func (factory *executionHooksFactory) preRunEFunc( } if createConfig { // Check if a project configuration is already present. - if err := factory.store.Load(); err == nil || !errors.Is(err, os.ErrNotExist) { + var err error + if factory.projectFile != "" { + err = factory.store.LoadFrom(factory.projectFile) + } else { + err = factory.store.Load() + } + if err == nil || !errors.Is(err, os.ErrNotExist) { return fmt.Errorf("%s: already initialized", factory.errorMessage) } @@ -417,7 +426,13 @@ func (factory *executionHooksFactory) preRunEFunc( } } else { // Load the project configuration. - if err := factory.store.Load(); os.IsNotExist(err) { + var err error + if factory.projectFile != "" { + err = factory.store.LoadFrom(factory.projectFile) + } else { + err = factory.store.Load() + } + if os.IsNotExist(err) { return fmt.Errorf("%s: failed to find configuration file, project must be initialized", factory.errorMessage) } else if err != nil { @@ -507,7 +522,13 @@ func (factory *executionHooksFactory) runEFunc() func(*cobra.Command, []string) // and executes the post-scaffold hook. func (factory *executionHooksFactory) postRunEFunc() func(*cobra.Command, []string) error { return func(*cobra.Command, []string) error { - if err := factory.store.Save(); err != nil { + var err error + if factory.projectFile != "" { + err = factory.store.SaveTo(factory.projectFile) + } else { + err = factory.store.Save() + } + if err != nil { return fmt.Errorf("%s: failed to save configuration file: %w", factory.errorMessage, err) } diff --git a/pkg/cli/root.go b/pkg/cli/root.go index b1fa1c77bc5..30f068bd28b 100644 --- a/pkg/cli/root.go +++ b/pkg/cli/root.go @@ -103,6 +103,7 @@ func (c CLI) newRootCmd() *cobra.Command { // Global flags for all subcommands. cmd.PersistentFlags().StringSlice(pluginsFlag, nil, "plugin keys to be used for this subcommand execution") + cmd.PersistentFlags().String(projectFileFlag, "", "path to the project configuration file (default \"PROJECT\")") // Register --project-version on the root command so that it shows up in help. cmd.Flags().String(projectVersionFlag, c.defaultProjectVersion.String(), "project version")