diff --git a/cmd/convert.go b/cmd/convert.go index 3b25f42fb..7fabc230d 100644 --- a/cmd/convert.go +++ b/cmd/convert.go @@ -2,7 +2,6 @@ package cmd import ( "fmt" - "log" "os" "github.com/kong/deck/convert" @@ -73,7 +72,7 @@ func newConvertCmd(deprecated bool) *cobra.Command { if deprecated { short = "[deprecated] use 'file convert' instead" execute = func(cmd *cobra.Command, args []string) error { - log.Println("Warning: the 'deck convert' command was deprecated and moved to 'deck file convert'") + cprint.UpdatePrintf("Warning: the 'deck convert' command was deprecated and moved to 'deck file convert'.\n") return executeConvert(cmd, args) } } diff --git a/cmd/diff.go b/cmd/diff.go index 8bb66ff92..5afca4ebd 100644 --- a/cmd/diff.go +++ b/cmd/diff.go @@ -3,6 +3,7 @@ package cmd import ( "fmt" + "github.com/kong/deck/cprint" "github.com/spf13/cobra" ) @@ -13,11 +14,26 @@ var ( diffWorkspace string ) +func executeDiff(cmd *cobra.Command, _ []string) error { + return syncMain(cmd.Context(), diffCmdKongStateFile, true, + diffCmdParallelism, 0, diffWorkspace) +} + // newDiffCmd represents the diff command -func newDiffCmd() *cobra.Command { +func newDiffCmd(deprecated bool) *cobra.Command { + short := "Diff the current entities in Kong with the one on disks" + execute := executeDiff + if deprecated { + short = "[deprecated] use 'kong diff' instead" + execute = func(cmd *cobra.Command, args []string) error { + cprint.UpdatePrintf("Warning: the 'deck diff' command was deprecated and moved to 'deck kong diff'.\n") + return executeDiff(cmd, args) + } + } + diffCmd := &cobra.Command{ Use: "diff", - Short: "Diff the current entities in Kong with the one on disks", + Short: short, Long: `The diff command is similar to a dry run of the 'decK sync' command. It loads entities from Kong and performs a diff with @@ -25,10 +41,7 @@ the entities in local files. This allows you to see the entities that will be created, updated, or deleted. `, Args: validateNoArgs, - RunE: func(cmd *cobra.Command, args []string) error { - return syncMain(cmd.Context(), diffCmdKongStateFile, true, - diffCmdParallelism, 0, diffWorkspace) - }, + RunE: execute, PreRunE: func(cmd *cobra.Command, args []string) error { if len(diffCmdKongStateFile) == 0 { return fmt.Errorf("a state file with Kong's configuration " + diff --git a/cmd/dump.go b/cmd/dump.go index b6b7bdfbc..d6e2b7845 100644 --- a/cmd/dump.go +++ b/cmd/dump.go @@ -5,6 +5,7 @@ import ( "fmt" "strings" + "github.com/kong/deck/cprint" "github.com/kong/deck/dump" "github.com/kong/deck/file" "github.com/kong/deck/state" @@ -34,101 +35,50 @@ func listWorkspaces(ctx context.Context, client *kong.Client) ([]string, error) return res, nil } -// newDumpCmd represents the dump command -func newDumpCmd() *cobra.Command { - dumpCmd := &cobra.Command{ - Use: "dump", - Short: "Export Kong configuration to a file", - Long: `The dump command reads all entities present in Kong -and writes them to a local file. +func executeDump(cmd *cobra.Command, _ []string) error { + ctx := cmd.Context() -The file can then be read using the sync command or diff command to -configure Kong.`, - Args: validateNoArgs, - RunE: func(cmd *cobra.Command, args []string) error { - ctx := cmd.Context() - - if yes, err := utils.ConfirmFileOverwrite(dumpCmdKongStateFile, dumpCmdStateFormat, assumeYes); err != nil { - return err - } else if !yes { - return nil - } + if yes, err := utils.ConfirmFileOverwrite(dumpCmdKongStateFile, dumpCmdStateFormat, assumeYes); err != nil { + return err + } else if !yes { + return nil + } - if inKonnectMode(nil) { - _ = sendAnalytics("dump", "", modeKonnect) - return dumpKonnectV2(ctx) - } + if inKonnectMode(nil) { + _ = sendAnalytics("dump", "", modeKonnect) + return dumpKonnectV2(ctx) + } - wsClient, err := utils.GetKongClient(rootConfig) - if err != nil { - return err - } + wsClient, err := utils.GetKongClient(rootConfig) + if err != nil { + return err + } - format := file.Format(strings.ToUpper(dumpCmdStateFormat)) + format := file.Format(strings.ToUpper(dumpCmdStateFormat)) - kongVersion, err := fetchKongVersion(ctx, rootConfig.ForWorkspace(dumpWorkspace)) + kongVersion, err := fetchKongVersion(ctx, rootConfig.ForWorkspace(dumpWorkspace)) + if err != nil { + return fmt.Errorf("reading Kong version: %w", err) + } + _ = sendAnalytics("dump", kongVersion, modeKong) + + // Kong Enterprise dump all workspace + if dumpAllWorkspaces { + if dumpWorkspace != "" { + return fmt.Errorf("workspace cannot be specified with --all-workspace flag") + } + if dumpCmdKongStateFile != "kong" { + return fmt.Errorf("output-file cannot be specified with --all-workspace flag") + } + workspaces, err := listWorkspaces(ctx, wsClient) + if err != nil { + return err + } + + for _, workspace := range workspaces { + wsClient, err := utils.GetKongClient(rootConfig.ForWorkspace(workspace)) if err != nil { - return fmt.Errorf("reading Kong version: %w", err) - } - _ = sendAnalytics("dump", kongVersion, modeKong) - - // Kong Enterprise dump all workspace - if dumpAllWorkspaces { - if dumpWorkspace != "" { - return fmt.Errorf("workspace cannot be specified with --all-workspace flag") - } - if dumpCmdKongStateFile != "kong" { - return fmt.Errorf("output-file cannot be specified with --all-workspace flag") - } - workspaces, err := listWorkspaces(ctx, wsClient) - if err != nil { - return err - } - - for _, workspace := range workspaces { - wsClient, err := utils.GetKongClient(rootConfig.ForWorkspace(workspace)) - if err != nil { - return err - } - - rawState, err := dump.Get(ctx, wsClient, dumpConfig) - if err != nil { - return fmt.Errorf("reading configuration from Kong: %w", err) - } - ks, err := state.Get(rawState) - if err != nil { - return fmt.Errorf("building state: %w", err) - } - - if err := file.KongStateToFile(ks, file.WriteConfig{ - SelectTags: dumpConfig.SelectorTags, - Workspace: workspace, - Filename: workspace, - FileFormat: format, - WithID: dumpWithID, - KongVersion: kongVersion, - }); err != nil { - return err - } - } - return nil - } - - // Kong OSS - // or Kong Enterprise single workspace - if dumpWorkspace != "" { - wsConfig := rootConfig.ForWorkspace(dumpWorkspace) - exists, err := workspaceExists(ctx, rootConfig, dumpWorkspace) - if err != nil { - return err - } - if !exists { - return fmt.Errorf("workspace '%v' does not exist in Kong", dumpWorkspace) - } - wsClient, err = utils.GetKongClient(wsConfig) - if err != nil { - return err - } + return err } rawState, err := dump.Get(ctx, wsClient, dumpConfig) @@ -139,15 +89,78 @@ configure Kong.`, if err != nil { return fmt.Errorf("building state: %w", err) } - return file.KongStateToFile(ks, file.WriteConfig{ + + if err := file.KongStateToFile(ks, file.WriteConfig{ SelectTags: dumpConfig.SelectorTags, - Workspace: dumpWorkspace, - Filename: dumpCmdKongStateFile, + Workspace: workspace, + Filename: workspace, FileFormat: format, WithID: dumpWithID, KongVersion: kongVersion, - }) - }, + }); err != nil { + return err + } + } + return nil + } + + // Kong OSS + // or Kong Enterprise single workspace + if dumpWorkspace != "" { + wsConfig := rootConfig.ForWorkspace(dumpWorkspace) + exists, err := workspaceExists(ctx, rootConfig, dumpWorkspace) + if err != nil { + return err + } + if !exists { + return fmt.Errorf("workspace '%v' does not exist in Kong", dumpWorkspace) + } + wsClient, err = utils.GetKongClient(wsConfig) + if err != nil { + return err + } + } + + rawState, err := dump.Get(ctx, wsClient, dumpConfig) + if err != nil { + return fmt.Errorf("reading configuration from Kong: %w", err) + } + ks, err := state.Get(rawState) + if err != nil { + return fmt.Errorf("building state: %w", err) + } + return file.KongStateToFile(ks, file.WriteConfig{ + SelectTags: dumpConfig.SelectorTags, + Workspace: dumpWorkspace, + Filename: dumpCmdKongStateFile, + FileFormat: format, + WithID: dumpWithID, + KongVersion: kongVersion, + }) +} + +// newDumpCmd represents the dump command +func newDumpCmd(deprecated bool) *cobra.Command { + short := "Export Kong configuration to a file" + execute := executeDump + if deprecated { + short = "[deprecated] use 'kong dump' instead" + execute = func(cmd *cobra.Command, args []string) error { + cprint.UpdatePrintf("Warning: the 'deck dump' command was deprecated and moved to 'deck kong dump'.\n") + return executeDump(cmd, args) + } + } + + dumpCmd := &cobra.Command{ + Use: "dump", + Short: short, + Long: `The dump command reads all entities present in Kong +and writes them to a local file. + +The file can then be read using the sync command or diff command to +configure Kong.`, + Args: validateNoArgs, + RunE: execute, } dumpCmd.Flags().StringVarP(&dumpCmdKongStateFile, "output-file", "o", diff --git a/cmd/file.go b/cmd/file.go index 50232e68c..b47acdf1f 100644 --- a/cmd/file.go +++ b/cmd/file.go @@ -13,12 +13,12 @@ import ( // // -func newAddFileCmd() *cobra.Command { - addFileCmd := &cobra.Command{ +func newFileSubCmd() *cobra.Command { + fileCmd := &cobra.Command{ Use: "file [sub-command]...", - Short: "Sub-command to host the decK file manipulation operations", - Long: `Sub-command to host the decK file manipulation operations`, + Short: "Sub-command to host the decK file operations", + Long: `Sub-command to host the decK file operations`, } - return addFileCmd + return fileCmd } diff --git a/cmd/kong.go b/cmd/kong.go new file mode 100644 index 000000000..db960e84c --- /dev/null +++ b/cmd/kong.go @@ -0,0 +1,24 @@ +/* +Copyright © 2023 NAME HERE +*/ +package cmd + +import ( + "github.com/spf13/cobra" +) + +// +// +// Define the CLI data for the kong sub-command +// +// + +func newKongSubCmd() *cobra.Command { + kongSubCmd := &cobra.Command{ + Use: "kong [sub-command]...", + Short: "Sub-command to host the decK network operations", + Long: `Sub-command to host the decK network operations`, + } + + return kongSubCmd +} diff --git a/cmd/konnect.go b/cmd/konnect.go index a5196c560..ace8c3410 100644 --- a/cmd/konnect.go +++ b/cmd/konnect.go @@ -14,7 +14,7 @@ might have breaking changes in future releases.` func newKonnectCmd() *cobra.Command { konnectCmd := &cobra.Command{ Use: "konnect", - Short: "Configuration tool for Konnect (in alpha)", + Short: "[deprecated] Configuration tool for Konnect", Long: `The konnect command prints subcommands that can be used to configure Konnect.` + konnectAlphaState, PersistentPreRun: func(cmd *cobra.Command, args []string) { diff --git a/cmd/ping.go b/cmd/ping.go index d2a6b0e76..85a572d8f 100644 --- a/cmd/ping.go +++ b/cmd/ping.go @@ -5,28 +5,41 @@ import ( "fmt" "net/url" + "github.com/kong/deck/cprint" "github.com/kong/deck/utils" "github.com/spf13/cobra" ) var pingWorkspace string +func executePing(cmd *cobra.Command, _ []string) error { + ctx := cmd.Context() + mode := getMode(nil) + if mode == modeKonnect { + return pingKonnect(ctx) + } + return pingKong(ctx) +} + // newPingCmd represents the ping command -func newPingCmd() *cobra.Command { +func newPingCmd(deprecated bool) *cobra.Command { + short := "Verify connectivity with Kong" + execute := executePing + if deprecated { + short = "[deprecated] use 'kong ping' instead" + execute = func(cmd *cobra.Command, args []string) error { + cprint.UpdatePrintf("Warning: the 'deck ping' command was deprecated and moved to 'deck kong ping'.\n") + return executePing(cmd, args) + } + } + pingCmd := &cobra.Command{ Use: "ping", - Short: "Verify connectivity with Kong", + Short: short, Long: `The ping command can be used to verify if decK can connect to Kong's Admin API.`, Args: validateNoArgs, - RunE: func(cmd *cobra.Command, args []string) error { - ctx := cmd.Context() - mode := getMode(nil) - if mode == modeKonnect { - return pingKonnect(ctx) - } - return pingKong(ctx) - }, + RunE: execute, } pingCmd.Flags().StringVarP(&pingWorkspace, "workspace", "w", diff --git a/cmd/reset.go b/cmd/reset.go index f9b7574ce..273b53f21 100644 --- a/cmd/reset.go +++ b/cmd/reset.go @@ -3,6 +3,7 @@ package cmd import ( "fmt" + "github.com/kong/deck/cprint" "github.com/kong/deck/state" "github.com/kong/deck/utils" "github.com/spf13/cobra" @@ -14,11 +15,102 @@ var ( resetAllWorkspaces bool ) +func executeReset(cmd *cobra.Command, _ []string) error { + ctx := cmd.Context() + + if resetAllWorkspaces && resetWorkspace != "" { + return fmt.Errorf("workspace cannot be specified with --all-workspace flag") + } + + if !resetCmdForce { + ok, err := utils.Confirm("This will delete all configuration from Kong's database." + + "\n> Are you sure? ") + if err != nil { + return err + } + if !ok { + return nil + } + } + + mode := getMode(nil) + if mode == modeKonnect { + _ = sendAnalytics("reset", "", mode) + return resetKonnectV2(ctx) + } + + rootClient, err := utils.GetKongClient(rootConfig) + if err != nil { + return err + } + + kongVersion, err := fetchKongVersion(ctx, rootConfig.ForWorkspace(resetWorkspace)) + if err != nil { + return fmt.Errorf("reading Kong version: %w", err) + } + _ = sendAnalytics("reset", kongVersion, mode) + + var workspaces []string + // Kong OSS or default workspace + if !resetAllWorkspaces && resetWorkspace == "" { + workspaces = append(workspaces, "") + } + + // Kong Enterprise + if resetAllWorkspaces { + workspaces, err = listWorkspaces(ctx, rootClient) + if err != nil { + return err + } + } + if resetWorkspace != "" { + exists, err := workspaceExists(ctx, rootConfig, resetWorkspace) + if err != nil { + return err + } + if !exists { + return fmt.Errorf("workspace '%v' does not exist in Kong", resetWorkspace) + } + + workspaces = append(workspaces, resetWorkspace) + } + + for _, workspace := range workspaces { + wsClient, err := utils.GetKongClient(rootConfig.ForWorkspace(workspace)) + if err != nil { + return err + } + currentState, err := fetchCurrentState(ctx, wsClient, dumpConfig) + if err != nil { + return err + } + targetState, err := state.NewKongState() + if err != nil { + return err + } + _, err = performDiff(ctx, currentState, targetState, false, 10, 0, wsClient, false) + if err != nil { + return err + } + } + return nil +} + // newResetCmd represents the reset command -func newResetCmd() *cobra.Command { +func newResetCmd(deprecated bool) *cobra.Command { + short := "Reset deletes all entities in Kong" + execute := executeReset + if deprecated { + short = "[deprecated] use 'kong reset' instead" + execute = func(cmd *cobra.Command, args []string) error { + cprint.UpdatePrintf("Warning: the 'deck reset' command was deprecated and moved to 'deck kong reset'.\n") + return executeReset(cmd, args) + } + } + resetCmd := &cobra.Command{ Use: "reset", - Short: "Reset deletes all entities in Kong", + Short: short, Long: `The reset command deletes all entities in Kong's database.string. Use this command with extreme care as it's equivalent to running @@ -26,86 +118,7 @@ Use this command with extreme care as it's equivalent to running By default, this command will ask for confirmation.`, Args: validateNoArgs, - RunE: func(cmd *cobra.Command, args []string) error { - ctx := cmd.Context() - - if resetAllWorkspaces && resetWorkspace != "" { - return fmt.Errorf("workspace cannot be specified with --all-workspace flag") - } - - if !resetCmdForce { - ok, err := utils.Confirm("This will delete all configuration from Kong's database." + - "\n> Are you sure? ") - if err != nil { - return err - } - if !ok { - return nil - } - } - - mode := getMode(nil) - if mode == modeKonnect { - _ = sendAnalytics("reset", "", mode) - return resetKonnectV2(ctx) - } - - rootClient, err := utils.GetKongClient(rootConfig) - if err != nil { - return err - } - - kongVersion, err := fetchKongVersion(ctx, rootConfig.ForWorkspace(resetWorkspace)) - if err != nil { - return fmt.Errorf("reading Kong version: %w", err) - } - _ = sendAnalytics("reset", kongVersion, mode) - - var workspaces []string - // Kong OSS or default workspace - if !resetAllWorkspaces && resetWorkspace == "" { - workspaces = append(workspaces, "") - } - - // Kong Enterprise - if resetAllWorkspaces { - workspaces, err = listWorkspaces(ctx, rootClient) - if err != nil { - return err - } - } - if resetWorkspace != "" { - exists, err := workspaceExists(ctx, rootConfig, resetWorkspace) - if err != nil { - return err - } - if !exists { - return fmt.Errorf("workspace '%v' does not exist in Kong", resetWorkspace) - } - - workspaces = append(workspaces, resetWorkspace) - } - - for _, workspace := range workspaces { - wsClient, err := utils.GetKongClient(rootConfig.ForWorkspace(workspace)) - if err != nil { - return err - } - currentState, err := fetchCurrentState(ctx, wsClient, dumpConfig) - if err != nil { - return err - } - targetState, err := state.NewKongState() - if err != nil { - return err - } - _, err = performDiff(ctx, currentState, targetState, false, 10, 0, wsClient, false) - if err != nil { - return err - } - } - return nil - }, + RunE: execute, } resetCmd.Flags().BoolVarP(&resetCmdForce, "force", "f", diff --git a/cmd/root.go b/cmd/root.go index f4712609b..6ed2b0ef3 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -204,18 +204,28 @@ It can be used to export, import, or sync entities to Kong.`, viper.BindPFlag("konnect-runtime-group-name", rootCmd.PersistentFlags().Lookup("konnect-runtime-group-name")) - rootCmd.AddCommand(newSyncCmd()) rootCmd.AddCommand(newVersionCmd()) - rootCmd.AddCommand(newValidateCmd()) - rootCmd.AddCommand(newResetCmd()) - rootCmd.AddCommand(newPingCmd()) - rootCmd.AddCommand(newDumpCmd()) - rootCmd.AddCommand(newDiffCmd()) - rootCmd.AddCommand(newConvertCmd(true)) // deprecated, to be removed rootCmd.AddCommand(newCompletionCmd()) - rootCmd.AddCommand(newKonnectCmd()) + rootCmd.AddCommand(newSyncCmd(true)) // deprecated, to be removed + rootCmd.AddCommand(newValidateCmd(true)) // deprecated, to be removed + rootCmd.AddCommand(newResetCmd(true)) // deprecated, to be removed + rootCmd.AddCommand(newPingCmd(true)) // deprecated, to be removed + rootCmd.AddCommand(newDumpCmd(true)) // deprecated, to be removed + rootCmd.AddCommand(newDiffCmd(true)) // deprecated, to be removed + rootCmd.AddCommand(newConvertCmd(true)) // deprecated, to be removed + rootCmd.AddCommand(newKonnectCmd()) // deprecated, to be removed { - fileCmd := newAddFileCmd() + kongCmd := newKongSubCmd() + rootCmd.AddCommand(kongCmd) + kongCmd.AddCommand(newSyncCmd(false)) + kongCmd.AddCommand(newValidateCmd(false)) + kongCmd.AddCommand(newResetCmd(false)) + kongCmd.AddCommand(newPingCmd(false)) + kongCmd.AddCommand(newDumpCmd(false)) + kongCmd.AddCommand(newDiffCmd(false)) + } + { + fileCmd := newFileSubCmd() rootCmd.AddCommand(fileCmd) fileCmd.AddCommand(newAddPluginsCmd()) fileCmd.AddCommand(newAddTagsCmd()) @@ -225,7 +235,7 @@ It can be used to export, import, or sync entities to Kong.`, fileCmd.AddCommand(newPatchCmd()) fileCmd.AddCommand(newOpenapi2KongCmd()) fileCmd.AddCommand(newConvertCmd(false)) - fileCmd.AddCommand(newValidateCmd()) // alias; since this does both file+online + fileCmd.AddCommand(newValidateCmd(false)) // alias; since this does both file+online } return rootCmd } diff --git a/cmd/sync.go b/cmd/sync.go index 856577d21..1bd9fadb0 100644 --- a/cmd/sync.go +++ b/cmd/sync.go @@ -3,6 +3,7 @@ package cmd import ( "fmt" + "github.com/kong/deck/cprint" "github.com/spf13/cobra" ) @@ -12,20 +13,32 @@ var ( syncWorkspace string ) +var syncCmdKongStateFile []string + +func executeSync(cmd *cobra.Command, _ []string) error { + return syncMain(cmd.Context(), syncCmdKongStateFile, false, + syncCmdParallelism, syncCmdDBUpdateDelay, syncWorkspace) +} + // newSyncCmd represents the sync command -func newSyncCmd() *cobra.Command { - var syncCmdKongStateFile []string +func newSyncCmd(deprecated bool) *cobra.Command { + short := "Sync performs operations to get Kong's configuration to match the state file" + execute := executeSync + if deprecated { + short = "[deprecated] use 'kong sync' instead" + execute = func(cmd *cobra.Command, args []string) error { + cprint.UpdatePrintf("Warning: the 'deck sync' command was deprecated and moved to 'deck kong sync'.\n") + return executeSync(cmd, args) + } + } + syncCmd := &cobra.Command{ - Use: "sync", - Short: "Sync performs operations to get Kong's configuration " + - "to match the state file", + Use: "sync", + Short: short, Long: `The sync command reads the state file and performs operation on Kong to get Kong's state in sync with the input state.`, Args: validateNoArgs, - RunE: func(cmd *cobra.Command, args []string) error { - return syncMain(cmd.Context(), syncCmdKongStateFile, false, - syncCmdParallelism, syncCmdDBUpdateDelay, syncWorkspace) - }, + RunE: execute, PreRunE: func(cmd *cobra.Command, args []string) error { if len(syncCmdKongStateFile) == 0 { return fmt.Errorf("a state file with Kong's configuration " + diff --git a/cmd/validate.go b/cmd/validate.go index 2035d9933..1453af9a6 100644 --- a/cmd/validate.go +++ b/cmd/validate.go @@ -4,6 +4,7 @@ import ( "context" "fmt" + "github.com/kong/deck/cprint" "github.com/kong/deck/dump" "github.com/kong/deck/file" "github.com/kong/deck/state" @@ -21,11 +22,70 @@ var ( validateParallelism int ) +func executeValidate(cmd *cobra.Command, _ []string) error { + mode := getMode(nil) + if validateOnline && mode == modeKonnect { + return fmt.Errorf("online validation not yet supported in konnect mode") + } + _ = sendAnalytics("validate", "", mode) + // read target file + // this does json schema validation as well + targetContent, err := file.GetContentFromFiles(validateCmdKongStateFile) + if err != nil { + return err + } + + dummyEmptyState, err := state.NewKongState() + if err != nil { + return err + } + ctx := cmd.Context() + var kongClient *kong.Client + if validateOnline { + kongClient, err = getKongClient(ctx, targetContent) + if err != nil { + return err + } + } + + rawState, err := file.Get(ctx, targetContent, file.RenderConfig{ + CurrentState: dummyEmptyState, + }, dump.Config{}, kongClient) + if err != nil { + return err + } + if err := checkForRBACResources(*rawState, validateCmdRBACResourcesOnly); err != nil { + return err + } + // this catches foreign relation errors + ks, err := state.Get(rawState) + if err != nil { + return err + } + + if validateOnline { + if errs := validateWithKong(ctx, kongClient, ks); len(errs) != 0 { + return validate.ErrorsWrapper{Errors: errs} + } + } + return nil +} + // newValidateCmd represents the diff command -func newValidateCmd() *cobra.Command { +func newValidateCmd(deprecated bool) *cobra.Command { + short := "Validate the state file" + execute := executeValidate + if deprecated { + short = "[deprecated] use 'kong validate' instead" + execute = func(cmd *cobra.Command, args []string) error { + cprint.UpdatePrintf("Warning: the 'deck validate' command was deprecated and moved to 'deck kong validate'.\n") + return executeValidate(cmd, args) + } + } + validateCmd := &cobra.Command{ Use: "validate", - Short: "Validate the state file", + Short: short, Long: `The validate command reads the state file and ensures validity. It reads all the specified state files and reports YAML/JSON parsing issues. It also checks for foreign relationships @@ -35,54 +95,7 @@ No communication takes places between decK and Kong during the execution of this command unless --online flag is used. `, Args: validateNoArgs, - RunE: func(cmd *cobra.Command, args []string) error { - mode := getMode(nil) - if validateOnline && mode == modeKonnect { - return fmt.Errorf("online validation not yet supported in konnect mode") - } - _ = sendAnalytics("validate", "", mode) - // read target file - // this does json schema validation as well - targetContent, err := file.GetContentFromFiles(validateCmdKongStateFile) - if err != nil { - return err - } - - dummyEmptyState, err := state.NewKongState() - if err != nil { - return err - } - ctx := cmd.Context() - var kongClient *kong.Client - if validateOnline { - kongClient, err = getKongClient(ctx, targetContent) - if err != nil { - return err - } - } - - rawState, err := file.Get(ctx, targetContent, file.RenderConfig{ - CurrentState: dummyEmptyState, - }, dump.Config{}, kongClient) - if err != nil { - return err - } - if err := checkForRBACResources(*rawState, validateCmdRBACResourcesOnly); err != nil { - return err - } - // this catches foreign relation errors - ks, err := state.Get(rawState) - if err != nil { - return err - } - - if validateOnline { - if errs := validateWithKong(ctx, kongClient, ks); len(errs) != 0 { - return validate.ErrorsWrapper{Errors: errs} - } - } - return nil - }, + RunE: execute, PreRunE: func(cmd *cobra.Command, args []string) error { if len(validateCmdKongStateFile) == 0 { return fmt.Errorf("a state file with Kong's configuration " +