Skip to content

Commit

Permalink
Implement the plugin phase 1.5 API
Browse files Browse the repository at this point in the history
Signed-off-by: Adrian Orive <[email protected]>
  • Loading branch information
Adirio committed Feb 8, 2021
1 parent 8b7e731 commit d17eb4e
Show file tree
Hide file tree
Showing 26 changed files with 1,149 additions and 1,336 deletions.
81 changes: 31 additions & 50 deletions pkg/cli/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,77 +14,58 @@ See the License for the specific language governing permissions and
limitations under the License.
*/

package cli // nolint:dupl
package cli //nolint:dupl

import (
"fmt"

"github.com/spf13/cobra"

yamlstore "sigs.k8s.io/kubebuilder/v3/pkg/config/store/yaml"
"sigs.k8s.io/kubebuilder/v3/pkg/plugin"
)

const apiErrorMsg = "failed to create API"

func (c cli) newCreateAPICmd() *cobra.Command {
ctx := c.newAPIContext()
cmd := &cobra.Command{
Use: "api",
Short: "Scaffold a Kubernetes API",
Long: ctx.Description,
Example: ctx.Examples,
Use: "api",
Short: "Scaffold a Kubernetes API",
Long: `Scaffold a Kubernetes API.
`,
RunE: errCmdFunc(
fmt.Errorf("api subcommand requires an existing project"),
),
}

// Lookup the plugin for projectVersion and bind it to the command.
c.bindCreateAPI(ctx, cmd)
return cmd
}

func (c cli) newAPIContext() plugin.Context {
return plugin.Context{
CommandName: c.commandName,
Description: `Scaffold a Kubernetes API.
`,
}
}

// nolint:dupl
func (c cli) bindCreateAPI(ctx plugin.Context, cmd *cobra.Command) {
// In case no plugin was resolved, instead of failing the construction of the CLI, fail the execution of
// this subcommand. This allows the use of subcommands that do not require resolved plugins like help.
if len(c.resolvedPlugins) == 0 {
cmdErr(cmd, fmt.Errorf(noPluginError))
return
cmdErr(cmd, noResolvedPluginError{})
return cmd
}

var createAPIPlugin plugin.CreateAPI
for _, p := range c.resolvedPlugins {
tmpPlugin, isValid := p.(plugin.CreateAPI)
if isValid {
if createAPIPlugin != nil {
err := fmt.Errorf("duplicate API creation plugins (%s, %s), use a more specific plugin key",
plugin.KeyFor(createAPIPlugin), plugin.KeyFor(p))
cmdErr(cmd, err)
return
}
createAPIPlugin = tmpPlugin
}
}
// Obtain the plugin keys and subcommands from the plugins that implement plugin.CreateAPI.
pluginKeys, subcommands := c.filterSubcommands(
func(p plugin.Plugin) bool {
_, isValid := p.(plugin.CreateAPI)
return isValid
},
func(p plugin.Plugin) plugin.Subcommand {
return p.(plugin.CreateAPI).GetCreateAPISubcommand()
},
)

if createAPIPlugin == nil {
cmdErr(cmd, fmt.Errorf("resolved plugins do not provide an API creation plugin: %v", c.pluginKeys))
return
// Verify that there is at least one remaining plugin.
if len(subcommands) == 0 {
cmdErr(cmd, noAvailablePluginError{"API creation"})
return cmd
}

subcommand := createAPIPlugin.GetCreateAPISubcommand()
subcommand.BindFlags(cmd.Flags())
subcommand.UpdateContext(&ctx)
cmd.Long = ctx.Description
cmd.Example = ctx.Examples
// Initialization methods.
options := c.initializationMethods(cmd, subcommands)

// Execution methods.
cmd.PreRunE, cmd.RunE, cmd.PostRunE = c.executionMethodsFuncs(pluginKeys, subcommands, options, apiErrorMsg)

cfg := yamlstore.New(c.fs)
msg := fmt.Sprintf("failed to create API with %q", plugin.KeyFor(createAPIPlugin))
cmd.PreRunE = preRunECmdFunc(subcommand, cfg, msg)
cmd.RunE = runECmdFunc(c.fs, subcommand, msg)
cmd.PostRunE = postRunECmdFunc(cfg, msg)
return cmd
}
9 changes: 7 additions & 2 deletions pkg/cli/cli.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,6 @@ const (

projectVersionFlag = "project-version"
pluginsFlag = "plugins"

noPluginError = "invalid config file please verify that the version and layout fields are set and valid"
)

// equalStringSlice checks if two string slices are equal.
Expand Down Expand Up @@ -480,6 +478,13 @@ func (c cli) printDeprecationWarnings() {
}
}

// metadata returns CLI's metadata.
func (c cli) metadata() plugin.CLIMetadata {
return plugin.CLIMetadata{
CommandName: c.commandName,
}
}

// Run implements CLI.Run.
func (c cli) Run() error {
return c.cmd.Execute()
Expand Down
Loading

0 comments on commit d17eb4e

Please sign in to comment.