Skip to content

Commit

Permalink
Merge branch 'inject-filesystem' into export-config-machinery
Browse files Browse the repository at this point in the history
  • Loading branch information
Adirio committed Mar 10, 2021
2 parents de84b80 + 1761213 commit 287b5ee
Show file tree
Hide file tree
Showing 32 changed files with 262 additions and 192 deletions.
4 changes: 2 additions & 2 deletions pkg/cli/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ func (c CLI) bindCreateAPI(ctx plugin.Context, cmd *cobra.Command) {
return
}

cfg, err := config.LoadInitialized()
cfg, err := config.LoadInitialized(c.fs)
if err != nil {
cmdErr(cmd, err)
return
Expand All @@ -88,6 +88,6 @@ func (c CLI) bindCreateAPI(ctx plugin.Context, cmd *cobra.Command) {
subcommand.UpdateContext(&ctx)
cmd.Long = ctx.Description
cmd.Example = ctx.Examples
cmd.RunE = runECmdFunc(cfg, subcommand,
cmd.RunE = runECmdFunc(c.fs, cfg, subcommand,
fmt.Sprintf("failed to create API with %q", plugin.KeyFor(createAPIPlugin)))
}
11 changes: 8 additions & 3 deletions pkg/cli/cli.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import (
"os"
"strings"

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

Expand Down Expand Up @@ -88,6 +89,9 @@ type CLI struct { //nolint:maligned

// Root command.
cmd *cobra.Command

// Underlying fs
fs afero.Fs
}

// New creates a new CLI instance.
Expand Down Expand Up @@ -131,6 +135,7 @@ func newCLI(options ...Option) (*CLI, error) {
defaultProjectVersion: cfgv3.Version,
defaultPlugins: make(map[config.Version][]string),
plugins: make(map[string]plugin.Plugin),
fs: afero.NewOsFs(),
}

// Apply provided options.
Expand Down Expand Up @@ -188,9 +193,9 @@ func (c *CLI) getInfoFromFlags() (string, []string, error) {
}

// getInfoFromConfigFile obtains the project version and plugin keys from the project config file.
func getInfoFromConfigFile() (config.Version, []string, error) {
func (c CLI) getInfoFromConfigFile() (config.Version, []string, error) {
// Read the project configuration file
projectConfig, err := internalconfig.Read()
projectConfig, err := internalconfig.Read(c.fs)
switch {
case err == nil:
case os.IsNotExist(err):
Expand Down Expand Up @@ -294,7 +299,7 @@ func (c *CLI) getInfo() error {
return err
}
// Get project version and plugin info from project configuration file
cfgProjectVersion, cfgPlugins, _ := getInfoFromConfigFile()
cfgProjectVersion, cfgPlugins, _ := c.getInfoFromConfigFile()
// We discard the error because not being able to read a project configuration file
// is not fatal for some commands. The ones that require it need to check its existence.

Expand Down
2 changes: 2 additions & 0 deletions pkg/cli/cli_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import (

. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
"github.com/spf13/afero"
"github.com/spf13/cobra"

"sigs.k8s.io/kubebuilder/v3/pkg/config"
Expand Down Expand Up @@ -585,6 +586,7 @@ var _ = Describe("CLI", func() {
defaultPlugins: map[config.Version][]string{
projectVersion: pluginKeys,
},
fs: afero.NewMemMapFs(),
}
c.cmd = c.newRootCmd()
Expect(c.getInfo()).To(Succeed())
Expand Down
4 changes: 3 additions & 1 deletion pkg/cli/cmd_helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ package cli
import (
"fmt"

"github.com/spf13/afero"
"github.com/spf13/cobra"

"sigs.k8s.io/kubebuilder/v3/pkg/cli/internal/config"
Expand Down Expand Up @@ -48,12 +49,13 @@ func errCmdFunc(err error) func(*cobra.Command, []string) error {
// runECmdFunc returns a cobra RunE function that runs subcommand and saves the
// config, which may have been modified by subcommand.
func runECmdFunc(
fs afero.Fs,
c *config.Config,
subcommand plugin.Subcommand,
msg string,
) func(*cobra.Command, []string) error {
return func(*cobra.Command, []string) error {
if err := subcommand.Run(); err != nil {
if err := subcommand.Run(fs); err != nil {
return fmt.Errorf("%s: %v", msg, err)
}
return c.Save()
Expand Down
4 changes: 2 additions & 2 deletions pkg/cli/edit.go
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ func (c CLI) bindEdit(ctx plugin.Context, cmd *cobra.Command) {
return
}

cfg, err := config.LoadInitialized()
cfg, err := config.LoadInitialized(c.fs)
if err != nil {
cmdErr(cmd, err)
return
Expand All @@ -88,6 +88,6 @@ func (c CLI) bindEdit(ctx plugin.Context, cmd *cobra.Command) {
subcommand.UpdateContext(&ctx)
cmd.Long = ctx.Description
cmd.Example = ctx.Examples
cmd.RunE = runECmdFunc(cfg, subcommand,
cmd.RunE = runECmdFunc(c.fs, cfg, subcommand,
fmt.Sprintf("failed to edit project with %q", plugin.KeyFor(editPlugin)))
}
6 changes: 3 additions & 3 deletions pkg/cli/init.go
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@ func (c CLI) bindInit(ctx plugin.Context, cmd *cobra.Command) {
return
}

cfg, err := internalconfig.New(c.projectVersion, internalconfig.DefaultPath)
cfg, err := internalconfig.New(c.fs, c.projectVersion, internalconfig.DefaultPath)
if err != nil {
cmdErr(cmd, fmt.Errorf("unable to initialize the project configuration: %w", err))
return
Expand All @@ -151,11 +151,11 @@ func (c CLI) bindInit(ctx plugin.Context, cmd *cobra.Command) {
cmd.RunE = func(*cobra.Command, []string) error {
// Check if a config is initialized in the command runner so the check
// doesn't erroneously fail other commands used in initialized projects.
_, err := internalconfig.Read()
_, err := internalconfig.Read(c.fs)
if err == nil || os.IsExist(err) {
log.Fatal("config already initialized")
}
if err := subcommand.Run(); err != nil {
if err := subcommand.Run(c.fs); err != nil {
return fmt.Errorf("failed to initialize project with %q: %v", plugin.KeyFor(initPlugin), err)
}
return cfg.Save()
Expand Down
26 changes: 11 additions & 15 deletions pkg/cli/internal/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -81,13 +81,13 @@ func readFrom(fs afero.Fs, path string) (config.Config, error) {
}

// Read obtains the configuration from the default path but doesn't allow to persist changes
func Read() (config.Config, error) {
return ReadFrom(DefaultPath)
func Read(fs afero.Fs) (config.Config, error) {
return ReadFrom(fs, DefaultPath)
}

// ReadFrom obtains the configuration from the provided path but doesn't allow to persist changes
func ReadFrom(path string) (config.Config, error) {
return readFrom(afero.NewOsFs(), path)
func ReadFrom(fs afero.Fs, path string) (config.Config, error) {
return readFrom(fs, path)
}

// Config extends model/config.Config allowing to persist changes
Expand All @@ -105,7 +105,7 @@ type Config struct {
}

// New creates a new configuration that will be stored at the provided path
func New(version config.Version, path string) (*Config, error) {
func New(fs afero.Fs, version config.Version, path string) (*Config, error) {
cfg, err := config.New(version)
if err != nil {
return nil, err
Expand All @@ -115,37 +115,33 @@ func New(version config.Version, path string) (*Config, error) {
Config: cfg,
path: path,
mustNotExist: true,
fs: afero.NewOsFs(),
fs: fs,
}, nil
}

// Load obtains the configuration from the default path allowing to persist changes (Save method)
func Load() (*Config, error) {
return LoadFrom(DefaultPath)
func Load(fs afero.Fs) (*Config, error) {
return LoadFrom(fs, DefaultPath)
}

// LoadInitialized calls Load() but returns helpful error messages if the config
// does not exist.
func LoadInitialized() (*Config, error) {
c, err := Load()
func LoadInitialized(fs afero.Fs) (*Config, error) {
c, err := Load(fs)
if os.IsNotExist(err) {
return nil, errors.New("unable to find configuration file, project must be initialized")
}
return c, err
}

// LoadFrom obtains the configuration from the provided path allowing to persist changes (Save method)
func LoadFrom(path string) (*Config, error) {
fs := afero.NewOsFs()
func LoadFrom(fs afero.Fs, path string) (*Config, error) {
c, err := readFrom(fs, path)
return &Config{Config: c, path: path, fs: fs}, err
}

// Save saves the configuration information
func (c Config) Save() error {
if c.fs == nil {
c.fs = afero.NewOsFs()
}
// If path is unset, it was created directly with `Config{}`
if c.path == "" {
return saveError{errors.New("no information where it should be stored, " +
Expand Down
4 changes: 2 additions & 2 deletions pkg/cli/webhook.go
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ func (c CLI) bindCreateWebhook(ctx plugin.Context, cmd *cobra.Command) {
return
}

cfg, err := config.LoadInitialized()
cfg, err := config.LoadInitialized(c.fs)
if err != nil {
cmdErr(cmd, err)
return
Expand All @@ -88,6 +88,6 @@ func (c CLI) bindCreateWebhook(ctx plugin.Context, cmd *cobra.Command) {
subcommand.UpdateContext(&ctx)
cmd.Long = ctx.Description
cmd.Example = ctx.Examples
cmd.RunE = runECmdFunc(cfg, subcommand,
cmd.RunE = runECmdFunc(c.fs, cfg, subcommand,
fmt.Sprintf("failed to create webhook with %q", plugin.KeyFor(createWebhookPlugin)))
}
3 changes: 2 additions & 1 deletion pkg/plugin/interfaces.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ limitations under the License.
package plugin

import (
"github.com/spf13/afero"
"github.com/spf13/pflag"

"sigs.k8s.io/kubebuilder/v3/pkg/config"
Expand Down Expand Up @@ -53,7 +54,7 @@ type Subcommand interface {
// command line flags.
BindFlags(*pflag.FlagSet)
// Run runs the subcommand.
Run() error
Run(fs afero.Fs) error
// InjectConfig passes a config to a plugin. The plugin may modify the config.
// Initializing, loading, and saving the config is managed by the cli package.
InjectConfig(config.Config)
Expand Down
15 changes: 4 additions & 11 deletions pkg/plugins/golang/v2/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,10 @@ import (
"bufio"
"errors"
"fmt"
"io/ioutil"
"os"
"path/filepath"
"strings"

"github.com/spf13/afero"
"github.com/spf13/pflag"

"sigs.k8s.io/kubebuilder/v3/pkg/config"
Expand Down Expand Up @@ -126,7 +125,7 @@ func (p *createAPISubcommand) InjectConfig(c config.Config) {
p.config = c
}

func (p *createAPISubcommand) Run() error {
func (p *createAPISubcommand) Run(fs afero.Fs) error {
// Ask for API and Controller if not specified
reader := bufio.NewReader(os.Stdin)
if !p.resourceFlag.Changed {
Expand All @@ -141,7 +140,7 @@ func (p *createAPISubcommand) Run() error {
// Create the resource from the options
p.resource = p.options.NewResource(p.config)

return cmdutil.Run(p)
return cmdutil.Run(p, fs)
}

func (p *createAPISubcommand) Validate() error {
Expand Down Expand Up @@ -171,12 +170,6 @@ func (p *createAPISubcommand) Validate() error {
}

func (p *createAPISubcommand) GetScaffolder() (cmdutil.Scaffolder, error) {
// Load the boilerplate
bp, err := ioutil.ReadFile(filepath.Join("hack", "boilerplate.go.txt")) // nolint:gosec
if err != nil {
return nil, fmt.Errorf("unable to load boilerplate: %v", err)
}

// Load the requested plugins
plugins := make([]model.Plugin, 0)
switch strings.ToLower(p.pattern) {
Expand All @@ -188,7 +181,7 @@ func (p *createAPISubcommand) GetScaffolder() (cmdutil.Scaffolder, error) {
return nil, fmt.Errorf("unknown pattern %q", p.pattern)
}

return scaffolds.NewAPIScaffolder(p.config, string(bp), p.resource, p.force, plugins), nil
return scaffolds.NewAPIScaffolder(p.config, p.resource, p.force, plugins), nil
}

func (p *createAPISubcommand) PostScaffold() error {
Expand Down
5 changes: 3 additions & 2 deletions pkg/plugins/golang/v2/edit.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ package v2
import (
"fmt"

"github.com/spf13/afero"
"github.com/spf13/pflag"

"sigs.k8s.io/kubebuilder/v3/pkg/config"
Expand Down Expand Up @@ -57,8 +58,8 @@ func (p *editSubcommand) InjectConfig(c config.Config) {
p.config = c
}

func (p *editSubcommand) Run() error {
return cmdutil.Run(p)
func (p *editSubcommand) Run(fs afero.Fs) error {
return cmdutil.Run(p, fs)
}

func (p *editSubcommand) Validate() error {
Expand Down
5 changes: 3 additions & 2 deletions pkg/plugins/golang/v2/init.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import (
"path/filepath"
"strings"

"github.com/spf13/afero"
"github.com/spf13/pflag"

"sigs.k8s.io/kubebuilder/v3/pkg/config"
Expand Down Expand Up @@ -110,8 +111,8 @@ func (p *initSubcommand) InjectConfig(c config.Config) {
p.config = c
}

func (p *initSubcommand) Run() error {
return cmdutil.Run(p)
func (p *initSubcommand) Run(fs afero.Fs) error {
return cmdutil.Run(p, fs)
}

func (p *initSubcommand) Validate() error {
Expand Down
Loading

0 comments on commit 287b5ee

Please sign in to comment.