diff --git a/internal/cmd/alpha/alpha.go b/internal/cmd/alpha/alpha.go index c5e50466d..89ca4c74f 100644 --- a/internal/cmd/alpha/alpha.go +++ b/internal/cmd/alpha/alpha.go @@ -5,13 +5,14 @@ import ( "github.com/kyma-project/cli.v3/internal/cmd/alpha/access" "github.com/kyma-project/cli.v3/internal/cmd/alpha/add" "github.com/kyma-project/cli.v3/internal/cmd/alpha/hana" - "github.com/kyma-project/cli.v3/internal/cmd/alpha/imageimport" "github.com/kyma-project/cli.v3/internal/cmd/alpha/modules" "github.com/kyma-project/cli.v3/internal/cmd/alpha/oidc" "github.com/kyma-project/cli.v3/internal/cmd/alpha/provision" "github.com/kyma-project/cli.v3/internal/cmd/alpha/referenceinstance" - "github.com/kyma-project/cli.v3/internal/cmd/alpha/registry" + "github.com/kyma-project/cli.v3/internal/cmd/alpha/registry/config" + "github.com/kyma-project/cli.v3/internal/cmd/alpha/registry/imageimport" "github.com/kyma-project/cli.v3/internal/cmd/alpha/remove" + "github.com/kyma-project/cli.v3/internal/cmd/alpha/templates" "github.com/kyma-project/cli.v3/internal/cmdcommon" "github.com/spf13/cobra" ) @@ -23,23 +24,28 @@ func NewAlphaCMD() (*cobra.Command, clierror.Error) { Long: `A set of alpha prototypes that may still change. Use in automations on your own risk.`, DisableFlagsInUseLine: true, } - config, err := cmdcommon.NewKymaConfig(cmd) + kymaConfig, err := cmdcommon.NewKymaConfig(cmd) if err != nil { return nil, err } - cmd.AddCommand(hana.NewHanaCMD(config)) + cmd.AddCommand(hana.NewHanaCMD(kymaConfig)) cmd.AddCommand(provision.NewProvisionCMD()) - cmd.AddCommand(referenceinstance.NewReferenceInstanceCMD(config)) - cmd.AddCommand(imageimport.NewImportCMD(config)) - cmd.AddCommand(access.NewAccessCMD(config)) - cmd.AddCommand(oidc.NewOIDCCMD(config)) - cmd.AddCommand(modules.NewModulesCMD(config)) - cmd.AddCommand(add.NewAddCMD(config)) - cmd.AddCommand(remove.NewRemoveCMD(config)) - cmd.AddCommand(registry.NewRegistryCMD(config)) + cmd.AddCommand(referenceinstance.NewReferenceInstanceCMD(kymaConfig)) + cmd.AddCommand(access.NewAccessCMD(kymaConfig)) + cmd.AddCommand(oidc.NewOIDCCMD(kymaConfig)) + cmd.AddCommand(modules.NewModulesCMD(kymaConfig)) + cmd.AddCommand(add.NewAddCMD(kymaConfig)) + cmd.AddCommand(remove.NewRemoveCMD(kymaConfig)) - cmds := cmdcommon.BuildExtensions(config) + cmds := cmdcommon.BuildExtensions(kymaConfig, &cmdcommon.TemplateCommandsList{ + // list of template commands deffinitions + Explain: templates.BuildExplainCommand, + }, cmdcommon.CoreCommandsMap{ + // map of available core commands + "registry_config": config.NewConfigCMD, + "registry_image-import": imageimport.NewImportCMD, + }) cmd.AddCommand(cmds...) return cmd, nil diff --git a/internal/cmd/alpha/imageimport/imageimport.go b/internal/cmd/alpha/registry/imageimport/imageimport.go similarity index 100% rename from internal/cmd/alpha/imageimport/imageimport.go rename to internal/cmd/alpha/registry/imageimport/imageimport.go diff --git a/internal/cmd/alpha/registry/registry.go b/internal/cmd/alpha/registry/registry.go deleted file mode 100644 index acf45047a..000000000 --- a/internal/cmd/alpha/registry/registry.go +++ /dev/null @@ -1,20 +0,0 @@ -package registry - -import ( - "github.com/kyma-project/cli.v3/internal/cmd/alpha/registry/config" - "github.com/kyma-project/cli.v3/internal/cmdcommon" - "github.com/spf13/cobra" -) - -func NewRegistryCMD(kymaConfig *cmdcommon.KymaConfig) *cobra.Command { - - cmd := &cobra.Command{ - Use: "registry", - Short: "Set of commands for Kyma registry", - Long: `Use this command manage resources related to Kyma registry`, - } - - cmd.AddCommand(config.NewConfigCMD(kymaConfig)) - - return cmd -} diff --git a/internal/cmdcommon/extension.go b/internal/cmdcommon/extension.go index e5d5f2166..2726c1a63 100644 --- a/internal/cmdcommon/extension.go +++ b/internal/cmdcommon/extension.go @@ -13,17 +13,17 @@ import ( "k8s.io/client-go/kubernetes" ) -func BuildExtensions(config *KymaConfig) []*cobra.Command { +func BuildExtensions(config *KymaConfig, availableTemplateCommands *TemplateCommandsList, availableCoreCommands CoreCommandsMap) []*cobra.Command { cmds := make([]*cobra.Command, len(config.Extensions)) for i, extension := range config.Extensions { - cmds[i] = buildCommandFromExtension(&extension) + cmds[i] = buildCommandFromExtension(config, &extension, availableTemplateCommands, availableCoreCommands) } return cmds } -func buildCommandFromExtension(extension *Extension) *cobra.Command { +func buildCommandFromExtension(config *KymaConfig, extension *Extension, availableTemplateCommands *TemplateCommandsList, availableCoreCommands CoreCommandsMap) *cobra.Command { cmd := &cobra.Command{ Use: extension.RootCommand.Name, Short: extension.RootCommand.Description, @@ -36,15 +36,17 @@ func buildCommandFromExtension(extension *Extension) *cobra.Command { } if extension.TemplateCommands != nil { - addGenericCommands(cmd, extension.TemplateCommands) + addGenericCommands(cmd, extension.TemplateCommands, availableTemplateCommands) } + addCoreCommands(cmd, config, extension.CoreCommands, availableCoreCommands) + return cmd } -func addGenericCommands(cmd *cobra.Command, genericCommands *TemplateCommands) { +func addGenericCommands(cmd *cobra.Command, genericCommands *TemplateCommands, availableTemplateCommands *TemplateCommandsList) { if genericCommands.ExplainCommand != nil { - cmd.AddCommand(templates.BuildExplainCommand(&templates.ExplainOptions{ + cmd.AddCommand(availableTemplateCommands.Explain(&templates.ExplainOptions{ Short: genericCommands.ExplainCommand.Description, Long: genericCommands.ExplainCommand.DescriptionLong, Output: genericCommands.ExplainCommand.Output, @@ -52,6 +54,18 @@ func addGenericCommands(cmd *cobra.Command, genericCommands *TemplateCommands) { } } +func addCoreCommands(cmd *cobra.Command, config *KymaConfig, extensionCoreCommands []CoreCommandInfo, availableCoreCommands CoreCommandsMap) { + for _, expectedCoreCommand := range extensionCoreCommands { + command, ok := availableCoreCommands[expectedCoreCommand.ActionID] + if !ok { + // commands doesn't exist in this version of cli and we will not process it + continue + } + + cmd.AddCommand(command(config)) + } +} + func ListExtensions(ctx context.Context, client kubernetes.Interface) (ExtensionList, error) { labelSelector := fmt.Sprintf("%s==%s", ExtensionLabelKey, ExtensionResourceLabelValue) cms, err := client.CoreV1().ConfigMaps("").List(ctx, metav1.ListOptions{ @@ -87,12 +101,17 @@ func parseResourceExtension(cmData map[string]string) (*Extension, error) { return nil, err } - resourceInfo, err := parseOptionalField[ResourceInfo](cmData, ExtensionResourceInfoKey) + resourceInfo, err := parseOptionalField[*ResourceInfo](cmData, ExtensionResourceInfoKey) if err != nil { return nil, err } - genericCommands, err := parseOptionalField[TemplateCommands](cmData, ExtensionGenericCommandsKey) + genericCommands, err := parseOptionalField[*TemplateCommands](cmData, ExtensionGenericCommandsKey) + if err != nil { + return nil, err + } + + coreCommands, err := parseOptionalField[[]CoreCommandInfo](cmData, ExtensionCoreCommandsKey) if err != nil { return nil, err } @@ -101,6 +120,7 @@ func parseResourceExtension(cmData map[string]string) (*Extension, error) { RootCommand: *rootCommand, Resource: resourceInfo, TemplateCommands: genericCommands, + CoreCommands: coreCommands, }, nil } @@ -115,14 +135,14 @@ func parseRequiredField[T any](cmData map[string]string, cmKey string) (*T, erro return &data, err } -func parseOptionalField[T any](cmData map[string]string, cmKey string) (*T, error) { +func parseOptionalField[T any](cmData map[string]string, cmKey string) (T, error) { + var data T dataBytes, ok := cmData[cmKey] if !ok { // skip because field is not required - return nil, nil + return data, nil } - var data T err := yaml.Unmarshal([]byte(dataBytes), &data) - return &data, err + return data, err } diff --git a/internal/cmdcommon/extension_test.go b/internal/cmdcommon/extension_test.go index 0e85998c2..3175bcc13 100644 --- a/internal/cmdcommon/extension_test.go +++ b/internal/cmdcommon/extension_test.go @@ -110,6 +110,10 @@ explain: description: test-description descriptionLong: test-description-long output: test-explain-output +`, + ExtensionCoreCommandsKey: ` +- actionID: test-action-id-1 +- actionID: test-action-id-2 `, }, } @@ -137,5 +141,13 @@ func fixTestExtension(name string) Extension { Output: "test-explain-output", }, }, + CoreCommands: []CoreCommandInfo{ + { + ActionID: "test-action-id-1", + }, + { + ActionID: "test-action-id-2", + }, + }, } } diff --git a/internal/cmdcommon/extension_types.go b/internal/cmdcommon/extension_types.go index a71321a95..25267ba0c 100644 --- a/internal/cmdcommon/extension_types.go +++ b/internal/cmdcommon/extension_types.go @@ -1,5 +1,10 @@ package cmdcommon +import ( + "github.com/kyma-project/cli.v3/internal/cmd/alpha/templates" + "github.com/spf13/cobra" +) + const ( ExtensionLabelKey = "kyma-cli/extension" ExtensionResourceLabelValue = "resource" @@ -7,8 +12,17 @@ const ( ExtensionResourceInfoKey = "resource" ExtensionRootCommandKey = "rootCommand" ExtensionGenericCommandsKey = "templateCommands" + ExtensionCoreCommandsKey = "coreCommands" ) +// map of allowed core commands in format ID: FUNC +type CoreCommandsMap map[string]func(*KymaConfig) *cobra.Command + +// allowed template commands +type TemplateCommandsList struct { + Explain func(*templates.ExplainOptions) *cobra.Command +} + type ExtensionList []Extension type Extension struct { @@ -19,6 +33,9 @@ type Extension struct { // configuration of generic commands (like 'create', 'delete', 'get', ...) which implementation is provided by the cli // most of these commands bases on the `Resource` field TemplateCommands *TemplateCommands + // configuration of buildin commands (like 'registry config') which implementation is provided by cli + // use this command to enable feature for a module + CoreCommands []CoreCommandInfo } type Scope string @@ -60,3 +77,8 @@ type TemplateCommands struct { // kyma explain ExplainCommand *ExplainCommand `yaml:"explain"` } + +type CoreCommandInfo struct { + // id of the functionality that cli will run when user use this command + ActionID string `yaml:"actionID"` +}