diff --git a/doc/ovhcloud_completion.md b/doc/ovhcloud_completion.md new file mode 100644 index 00000000..b8a2f029 --- /dev/null +++ b/doc/ovhcloud_completion.md @@ -0,0 +1,58 @@ +## ovhcloud completion + +Generate shell completion scripts + +### Synopsis + +Generate shell completion scripts for ovhcloud CLI. + +To load completions in your current shell session: + + bash: + source <(ovhcloud completion bash) + + zsh: + source <(ovhcloud completion zsh) + + fish: + ovhcloud completion fish | source + +To make completions permanent, run: + + ovhcloud completion install + + +``` +ovhcloud completion [bash|zsh|fish|powershell] [flags] +``` + +### Options + +``` + -h, --help help for completion +``` + +### Options inherited from parent commands + +``` + -d, --debug Activate debug mode (will log all HTTP requests details) + -e, --ignore-errors Ignore errors in API calls when it is not fatal to the execution + -o, --output string Output format: json, yaml, interactive, or a custom format expression (using https://github.com/PaesslerAG/gval syntax) + Examples: + --output json + --output yaml + --output interactive + --output 'id' (to extract a single field) + --output 'nested.field.subfield' (to extract a nested field) + --output '[id, "name"]' (to extract multiple fields as an array) + --output '{"newKey": oldKey, "otherKey": nested.field}' (to extract and rename fields in an object) + --output 'name+","+type' (to extract and concatenate fields in a string) + --output '(nbFieldA + nbFieldB) * 10' (to compute values from numeric fields) + --profile string Use a specific profile from the configuration file +``` + +### SEE ALSO + +* [ovhcloud](ovhcloud.md) - CLI to manage your OVHcloud services +* [ovhcloud completion install](ovhcloud_completion_install.md) - Install shell completion permanently in your shell rc file + diff --git a/doc/ovhcloud_completion_install.md b/doc/ovhcloud_completion_install.md new file mode 100644 index 00000000..ce97f4cb --- /dev/null +++ b/doc/ovhcloud_completion_install.md @@ -0,0 +1,37 @@ +## ovhcloud completion install + +Install shell completion permanently in your shell rc file + +``` +ovhcloud completion install [flags] +``` + +### Options + +``` + -h, --help help for install +``` + +### Options inherited from parent commands + +``` + -d, --debug Activate debug mode (will log all HTTP requests details) + -e, --ignore-errors Ignore errors in API calls when it is not fatal to the execution + -o, --output string Output format: json, yaml, interactive, or a custom format expression (using https://github.com/PaesslerAG/gval syntax) + Examples: + --output json + --output yaml + --output interactive + --output 'id' (to extract a single field) + --output 'nested.field.subfield' (to extract a nested field) + --output '[id, "name"]' (to extract multiple fields as an array) + --output '{"newKey": oldKey, "otherKey": nested.field}' (to extract and rename fields in an object) + --output 'name+","+type' (to extract and concatenate fields in a string) + --output '(nbFieldA + nbFieldB) * 10' (to compute values from numeric fields) + --profile string Use a specific profile from the configuration file +``` + +### SEE ALSO + +* [ovhcloud completion](ovhcloud_completion.md) - Generate shell completion scripts + diff --git a/internal/cmd/account.go b/internal/cmd/account.go index c40850c9..1f69eddf 100644 --- a/internal/cmd/account.go +++ b/internal/cmd/account.go @@ -6,6 +6,7 @@ package cmd import ( "github.com/ovh/ovhcloud-cli/internal/assets" + "github.com/ovh/ovhcloud-cli/internal/completion" "github.com/ovh/ovhcloud-cli/internal/services/account" "github.com/spf13/cobra" ) @@ -63,10 +64,11 @@ func init() { })) oauth2ClientCmd.AddCommand(&cobra.Command{ - Use: "get ", - Short: "Get details of an OAuth2 client", - Args: cobra.ExactArgs(1), - Run: account.GetOauth2Client, + Use: "get ", + Short: "Get details of an OAuth2 client", + Args: cobra.ExactArgs(1), + ValidArgsFunction: completion.ServiceList("/v1/me/api/oauth2/client"), + Run: account.GetOauth2Client, }) oauth2CreateCmd := &cobra.Command{ @@ -85,17 +87,19 @@ func init() { oauth2ClientCmd.AddCommand(oauth2CreateCmd) oauth2ClientCmd.AddCommand(&cobra.Command{ - Use: "delete ", - Short: "Delete the given OAuth2 client", - Args: cobra.ExactArgs(1), - Run: account.DeleteOauth2Client, + Use: "delete ", + Short: "Delete the given OAuth2 client", + Args: cobra.ExactArgs(1), + ValidArgsFunction: completion.ServiceList("/v1/me/api/oauth2/client"), + Run: account.DeleteOauth2Client, }) oauth2ClientEditCmd := &cobra.Command{ - Use: "edit ", - Short: "Edit an OAuth2 client", - Args: cobra.ExactArgs(1), - Run: account.EditOauth2Client, + Use: "edit ", + Short: "Edit an OAuth2 client", + Args: cobra.ExactArgs(1), + ValidArgsFunction: completion.ServiceList("/v1/me/api/oauth2/client"), + Run: account.EditOauth2Client, } oauth2ClientEditCmd.Flags().StringArrayVar(&account.Oauth2ClientSpec.CallbackUrls, "callback-urls", nil, "Callback URLs for the OAuth2 client") oauth2ClientEditCmd.Flags().StringVar(&account.Oauth2ClientSpec.Description, "description", "", "Description of the OAuth2 client") diff --git a/internal/cmd/alldom.go b/internal/cmd/alldom.go index a2881036..d0740033 100644 --- a/internal/cmd/alldom.go +++ b/internal/cmd/alldom.go @@ -5,6 +5,7 @@ package cmd import ( + "github.com/ovh/ovhcloud-cli/internal/completion" "github.com/ovh/ovhcloud-cli/internal/services/alldom" "github.com/spf13/cobra" ) @@ -26,10 +27,11 @@ func init() { // Command to get a single AllDom alldomCmd.AddCommand(&cobra.Command{ - Use: "get ", - Short: "Retrieve information of a specific AllDom", - Args: cobra.ExactArgs(1), - Run: alldom.GetAllDom, + Use: "get ", + Short: "Retrieve information of a specific AllDom", + Args: cobra.ExactArgs(1), + ValidArgsFunction: completion.ServiceList("/v1/allDom"), + Run: alldom.GetAllDom, }) rootCmd.AddCommand(alldomCmd) diff --git a/internal/cmd/baremetal.go b/internal/cmd/baremetal.go index 532073b7..0f6897dc 100644 --- a/internal/cmd/baremetal.go +++ b/internal/cmd/baremetal.go @@ -6,6 +6,7 @@ package cmd import ( "github.com/ovh/ovhcloud-cli/internal/assets" + "github.com/ovh/ovhcloud-cli/internal/completion" "github.com/ovh/ovhcloud-cli/internal/flags" "github.com/ovh/ovhcloud-cli/internal/services/baremetal" "github.com/spf13/cobra" @@ -28,18 +29,20 @@ func init() { // Command to get a single Baremetal baremetalCmd.AddCommand(&cobra.Command{ - Use: "get ", - Short: "Retrieve information of a specific baremetal", - Args: cobra.ExactArgs(1), - Run: baremetal.GetBaremetal, + Use: "get ", + Short: "Retrieve information of a specific baremetal", + Args: cobra.ExactArgs(1), + ValidArgsFunction: completion.ServiceList("/v1/dedicated/server"), + Run: baremetal.GetBaremetal, }) // Command to edit a single Baremetal editBaremetalCmd := &cobra.Command{ - Use: "edit ", - Short: "Update the given baremetal", - Args: cobra.ExactArgs(1), - Run: baremetal.EditBaremetal, + Use: "edit ", + Short: "Update the given baremetal", + Args: cobra.ExactArgs(1), + ValidArgsFunction: completion.ServiceList("/v1/dedicated/server"), + Run: baremetal.EditBaremetal, } editBaremetalCmd.Flags().IntVar(&baremetal.EditBaremetalParams.BootId, "boot-id", 0, "Boot ID") editBaremetalCmd.Flags().StringVar(&baremetal.EditBaremetalParams.BootScript, "boot-script", "", "Boot script") @@ -55,28 +58,31 @@ func init() { // Command to list baremetal tasks baremetalListTasksCmd := &cobra.Command{ - Use: "list-tasks ", - Short: "Retrieve tasks of the given baremetal", - Args: cobra.ExactArgs(1), - Run: baremetal.ListBaremetalTasks, + Use: "list-tasks ", + Short: "Retrieve tasks of the given baremetal", + Args: cobra.ExactArgs(1), + ValidArgsFunction: completion.ServiceList("/v1/dedicated/server"), + Run: baremetal.ListBaremetalTasks, } baremetalCmd.AddCommand(withFilterFlag(baremetalListTasksCmd)) // Command to reboot a baremetal baremetalRebootCmd := &cobra.Command{ - Use: "reboot ", - Short: "Reboot the given baremetal", - Args: cobra.ExactArgs(1), - Run: baremetal.RebootBaremetal, + Use: "reboot ", + Short: "Reboot the given baremetal", + Args: cobra.ExactArgs(1), + ValidArgsFunction: completion.ServiceList("/v1/dedicated/server"), + Run: baremetal.RebootBaremetal, } baremetalCmd.AddCommand(baremetalRebootCmd) // Command to reboot a baremetal in rescue mode baremetalRebootRescueCmd := &cobra.Command{ - Use: "reboot-rescue ", - Short: "Reboot the given baremetal in rescue mode", - Args: cobra.ExactArgs(1), - Run: baremetal.RebootRescueBaremetal, + Use: "reboot-rescue ", + Short: "Reboot the given baremetal in rescue mode", + Args: cobra.ExactArgs(1), + ValidArgsFunction: completion.ServiceList("/v1/dedicated/server"), + Run: baremetal.RebootRescueBaremetal, } baremetalRebootRescueCmd.Flags().BoolVar(&flags.WaitForTask, "wait", false, "Wait for reboot to be done before exiting") baremetalCmd.AddCommand(baremetalRebootRescueCmd) @@ -127,9 +133,10 @@ to see all the available parameters and real life examples. Please note that all parameters are not compatible with all OSes. `, - Args: cobra.MaximumNArgs(1), - ArgAliases: []string{"service_name"}, - Run: baremetal.ReinstallBaremetal, + Args: cobra.MaximumNArgs(1), + ArgAliases: []string{"service_name"}, + ValidArgsFunction: completion.ServiceList("/v1/dedicated/server"), + Run: baremetal.ReinstallBaremetal, } addParameterFileFlags(reinstallBaremetalCmd, false, assets.BaremetalOpenapiSchema, "/dedicated/server/{serviceName}/reinstall", "post", baremetal.BaremetalInstallationExample, nil) @@ -158,24 +165,27 @@ Please note that all parameters are not compatible with all OSes. } baremetalCmd.AddCommand(baremetalBootCmd) baremetalBootCmd.AddCommand(withFilterFlag(&cobra.Command{ - Use: "list ", - Aliases: []string{"ls"}, - Short: "List boot options for the given baremetal", - Args: cobra.ExactArgs(1), - Run: baremetal.ListBaremetalBoots, + Use: "list ", + Aliases: []string{"ls"}, + Short: "List boot options for the given baremetal", + Args: cobra.ExactArgs(1), + ValidArgsFunction: completion.ServiceList("/v1/dedicated/server"), + Run: baremetal.ListBaremetalBoots, })) baremetalBootCmd.AddCommand(&cobra.Command{ - Use: "set ", - Short: "Configure a boot ID on the given baremetal", - Args: cobra.ExactArgs(2), - Run: baremetal.SetBaremetalBootId, + Use: "set ", + Short: "Configure a boot ID on the given baremetal", + Args: cobra.ExactArgs(2), + ValidArgsFunction: completion.ServiceList("/v1/dedicated/server"), + Run: baremetal.SetBaremetalBootId, }) baremetalBootSetScriptCmd := &cobra.Command{ - Use: "set-script ", - Short: "Configure a boot script on the given baremetal", - Args: cobra.ExactArgs(1), - Run: baremetal.SetBaremetalBootScript, + Use: "set-script ", + Short: "Configure a boot script on the given baremetal", + Args: cobra.ExactArgs(1), + ValidArgsFunction: completion.ServiceList("/v1/dedicated/server"), + Run: baremetal.SetBaremetalBootScript, } baremetalBootSetScriptCmd.Flags().StringVar(&baremetal.EditBaremetalParams.BootScript, "script", "", "Boot script to set on the baremetal") addInteractiveEditorFlag(baremetalBootSetScriptCmd) @@ -185,32 +195,36 @@ Please note that all parameters are not compatible with all OSes. baremetalBootCmd.AddCommand(baremetalBootSetScriptCmd) baremetalListInterventionsCmd := &cobra.Command{ - Use: "list-interventions ", - Short: "List past and planned interventions for the given baremetal", - Args: cobra.ExactArgs(1), - Run: baremetal.ListBaremetalInterventions, + Use: "list-interventions ", + Short: "List past and planned interventions for the given baremetal", + Args: cobra.ExactArgs(1), + ValidArgsFunction: completion.ServiceList("/v1/dedicated/server"), + Run: baremetal.ListBaremetalInterventions, } baremetalCmd.AddCommand(withFilterFlag(baremetalListInterventionsCmd)) baremetalCmd.AddCommand(withFilterFlag(&cobra.Command{ - Use: "list-ips ", - Short: "List all IPs that are routed to the given baremetal", - Args: cobra.ExactArgs(1), - Run: baremetal.GetBaremetalRelatedIPs, + Use: "list-ips ", + Short: "List all IPs that are routed to the given baremetal", + Args: cobra.ExactArgs(1), + ValidArgsFunction: completion.ServiceList("/v1/dedicated/server"), + Run: baremetal.GetBaremetalRelatedIPs, })) baremetalCmd.AddCommand(withFilterFlag(&cobra.Command{ - Use: "list-secrets ", - Short: "Retrieve secrets to connect to the server", - Args: cobra.ExactArgs(1), - Run: baremetal.GetBaremetalAuthenticationSecrets, + Use: "list-secrets ", + Short: "Retrieve secrets to connect to the server", + Args: cobra.ExactArgs(1), + ValidArgsFunction: completion.ServiceList("/v1/dedicated/server"), + Run: baremetal.GetBaremetalAuthenticationSecrets, })) baremetalCmd.AddCommand(withFilterFlag(&cobra.Command{ - Use: "list-compatible-os ", - Short: "Retrieve OSes that can be installed on this baremetal", - Args: cobra.ExactArgs(1), - Run: baremetal.GetBaremetalCompatibleOses, + Use: "list-compatible-os ", + Short: "Retrieve OSes that can be installed on this baremetal", + Args: cobra.ExactArgs(1), + ValidArgsFunction: completion.ServiceList("/v1/dedicated/server"), + Run: baremetal.GetBaremetalCompatibleOses, })) // Commands to manage virtual network interfaces @@ -220,17 +234,19 @@ Please note that all parameters are not compatible with all OSes. } baremetalCmd.AddCommand(baremetalVNICmd) baremetalVNICmd.AddCommand(withFilterFlag(&cobra.Command{ - Use: "list ", - Aliases: []string{"ls"}, - Short: "List Virtual Network Interfaces of the given baremetal", - Args: cobra.ExactArgs(1), - Run: baremetal.ListBaremetalVNIs, + Use: "list ", + Aliases: []string{"ls"}, + Short: "List Virtual Network Interfaces of the given baremetal", + Args: cobra.ExactArgs(1), + ValidArgsFunction: completion.ServiceList("/v1/dedicated/server"), + Run: baremetal.ListBaremetalVNIs, })) baremetalVNICreateOLAAggregationCmd := &cobra.Command{ - Use: "ola-create-aggregation --name --interface --interface ", - Short: "Group interfaces into an aggregation", - Args: cobra.ExactArgs(1), - Run: baremetal.CreateBaremetalOLAAggregation, + Use: "ola-create-aggregation --name --interface --interface ", + Short: "Group interfaces into an aggregation", + Args: cobra.ExactArgs(1), + ValidArgsFunction: completion.ServiceList("/v1/dedicated/server"), + Run: baremetal.CreateBaremetalOLAAggregation, } baremetalVNICreateOLAAggregationCmd.Flags().StringArrayVar(&baremetal.BaremetalOLAInterfaces, "interface", nil, "Interfaces to group") baremetalVNICreateOLAAggregationCmd.MarkFlagRequired("interface") @@ -239,10 +255,11 @@ Please note that all parameters are not compatible with all OSes. baremetalVNICmd.AddCommand(baremetalVNICreateOLAAggregationCmd) baremetalVNIResetOLAAggregationCmd := &cobra.Command{ - Use: "ola-reset --interface --interface ", - Short: "Reset interfaces to default configuration", - Args: cobra.ExactArgs(1), - Run: baremetal.ResetBaremetalOLAAggregation, + Use: "ola-reset --interface --interface ", + Short: "Reset interfaces to default configuration", + Args: cobra.ExactArgs(1), + ValidArgsFunction: completion.ServiceList("/v1/dedicated/server"), + Run: baremetal.ResetBaremetalOLAAggregation, } baremetalVNIResetOLAAggregationCmd.Flags().StringArrayVar(&baremetal.BaremetalOLAInterfaces, "interface", nil, "Interfaces to group") baremetalVNIResetOLAAggregationCmd.MarkFlagRequired("interface") @@ -255,10 +272,11 @@ Please note that all parameters are not compatible with all OSes. baremetalCmd.AddCommand(baremetalIPMICmd) baremetalIPMIGetAccessCmd := &cobra.Command{ - Use: "get-access --type serialOverLanURL --ttl 5", - Short: "Request an acces on KVM IPMI interface", - Args: cobra.ExactArgs(1), - Run: baremetal.BaremetalGetIPMIAccess, + Use: "get-access --type serialOverLanURL --ttl 5", + Short: "Request an acces on KVM IPMI interface", + Args: cobra.ExactArgs(1), + ValidArgsFunction: completion.ServiceList("/v1/dedicated/server"), + Run: baremetal.BaremetalGetIPMIAccess, } baremetalIPMIGetAccessCmd.Flags().IntVar(&baremetal.BaremetalIpmiTTL, "ttl", 1, "Time to live in minutes for cache (1, 3, 5, 10, 15)") baremetalIPMIGetAccessCmd.MarkFlagRequired("ttl") @@ -269,10 +287,11 @@ Please note that all parameters are not compatible with all OSes. baremetalIPMICmd.AddCommand(baremetalIPMIGetAccessCmd) baremetalIPMICmd.AddCommand(&cobra.Command{ - Use: "reset-sessions ", - Short: "Reset IPMI sessions on a baremetal server", - Args: cobra.ExactArgs(1), - Run: baremetal.BaremetalResetIPMISessions, + Use: "reset-sessions ", + Short: "Reset IPMI sessions on a baremetal server", + Args: cobra.ExactArgs(1), + ValidArgsFunction: completion.ServiceList("/v1/dedicated/server"), + Run: baremetal.BaremetalResetIPMISessions, }) rootCmd.AddCommand(baremetalCmd) diff --git a/internal/cmd/cdndedicated.go b/internal/cmd/cdndedicated.go index 4ed47830..2dadfd01 100644 --- a/internal/cmd/cdndedicated.go +++ b/internal/cmd/cdndedicated.go @@ -5,6 +5,7 @@ package cmd import ( + "github.com/ovh/ovhcloud-cli/internal/completion" "github.com/ovh/ovhcloud-cli/internal/services/cdndedicated" "github.com/spf13/cobra" ) @@ -26,10 +27,11 @@ func init() { // Command to get a single CdnDedicated cdndedicatedCmd.AddCommand(&cobra.Command{ - Use: "get ", - Short: "Retrieve information of a specific CDN", - Args: cobra.ExactArgs(1), - Run: cdndedicated.GetCdnDedicated, + Use: "get ", + Short: "Retrieve information of a specific CDN", + Args: cobra.ExactArgs(1), + ValidArgsFunction: completion.ServiceList("/v1/cdn/dedicated"), + Run: cdndedicated.GetCdnDedicated, }) rootCmd.AddCommand(cdndedicatedCmd) diff --git a/internal/cmd/cloud_alerting.go b/internal/cmd/cloud_alerting.go index 79d7c256..4bf3ae17 100644 --- a/internal/cmd/cloud_alerting.go +++ b/internal/cmd/cloud_alerting.go @@ -6,6 +6,7 @@ package cmd import ( "github.com/ovh/ovhcloud-cli/internal/assets" + "github.com/ovh/ovhcloud-cli/internal/completion" "github.com/ovh/ovhcloud-cli/internal/services/cloud" "github.com/spf13/cobra" ) @@ -28,10 +29,11 @@ func initCloudAlertingCommand(cloudCmd *cobra.Command) { // Get specific alerting configuration alertingCmd.AddCommand(&cobra.Command{ - Use: "get ", - Short: "Get a specific billing alert configuration", - Run: cloud.GetCloudAlertingConfig, - Args: cobra.ExactArgs(1), + Use: "get ", + Short: "Get a specific billing alert configuration", + ValidArgsFunction: completion.CloudResources("/v1/cloud/project/%s/alerting"), + Run: cloud.GetCloudAlertingConfig, + Args: cobra.ExactArgs(1), }) // Create alerting configuration @@ -52,10 +54,11 @@ func initCloudAlertingCommand(cloudCmd *cobra.Command) { // Edit alerting configuration alertingEditCmd := &cobra.Command{ - Use: "edit ", - Short: "Edit a billing alert configuration", - Run: cloud.EditCloudAlertingConfig, - Args: cobra.ExactArgs(1), + Use: "edit ", + Short: "Edit a billing alert configuration", + ValidArgsFunction: completion.CloudResources("/v1/cloud/project/%s/alerting"), + Run: cloud.EditCloudAlertingConfig, + Args: cobra.ExactArgs(1), } alertingEditCmd.Flags().Int64Var(&cloud.AlertingConfigEditSpec.Delay, "delay", 0, "Delay between alerts in seconds (minimum 3600)") alertingEditCmd.Flags().StringSliceVar(&cloud.AlertingConfigEditSpec.Emails, "emails", nil, "Email addresses to receive alerts (comma-separated)") @@ -68,10 +71,11 @@ func initCloudAlertingCommand(cloudCmd *cobra.Command) { // Delete alerting configuration alertingCmd.AddCommand(&cobra.Command{ - Use: "delete ", - Short: "Delete a billing alert configuration", - Run: cloud.DeleteCloudAlertingConfig, - Args: cobra.ExactArgs(1), + Use: "delete ", + Short: "Delete a billing alert configuration", + ValidArgsFunction: completion.CloudResources("/v1/cloud/project/%s/alerting"), + Run: cloud.DeleteCloudAlertingConfig, + Args: cobra.ExactArgs(1), }) // Subcommand for triggered alerts @@ -83,20 +87,22 @@ func initCloudAlertingCommand(cloudCmd *cobra.Command) { // List triggered alerts triggeredAlertListCmd := &cobra.Command{ - Use: "list ", - Aliases: []string{"ls"}, - Short: "List triggered alerts for a specific alert configuration", - Run: cloud.ListCloudAlertingTriggeredAlerts, - Args: cobra.ExactArgs(1), + Use: "list ", + Aliases: []string{"ls"}, + Short: "List triggered alerts for a specific alert configuration", + ValidArgsFunction: completion.CloudResources("/v1/cloud/project/%s/alerting"), + Run: cloud.ListCloudAlertingTriggeredAlerts, + Args: cobra.ExactArgs(1), } triggeredAlertCmd.AddCommand(withFilterFlag(triggeredAlertListCmd)) // Get specific triggered alert triggeredAlertCmd.AddCommand(&cobra.Command{ - Use: "get ", - Short: "Get a specific triggered alert", - Run: cloud.GetCloudAlertingTriggeredAlert, - Args: cobra.ExactArgs(2), + Use: "get ", + Short: "Get a specific triggered alert", + ValidArgsFunction: completion.CloudResources("/v1/cloud/project/%s/alerting"), + Run: cloud.GetCloudAlertingTriggeredAlert, + Args: cobra.ExactArgs(2), }) cloudCmd.AddCommand(alertingCmd) diff --git a/internal/cmd/cloud_instance.go b/internal/cmd/cloud_instance.go index 16d1baeb..207a3245 100644 --- a/internal/cmd/cloud_instance.go +++ b/internal/cmd/cloud_instance.go @@ -8,6 +8,7 @@ import ( "runtime" "github.com/ovh/ovhcloud-cli/internal/assets" + "github.com/ovh/ovhcloud-cli/internal/completion" "github.com/ovh/ovhcloud-cli/internal/flags" "github.com/ovh/ovhcloud-cli/internal/services/cloud" "github.com/spf13/cobra" @@ -156,40 +157,45 @@ func initInstanceCommand(cloudCmd *cobra.Command) { instanceCmd.AddCommand(withFilterFlag(instanceListCmd)) instanceCmd.AddCommand(&cobra.Command{ - Use: "get ", - Short: "Get a specific instance", - Run: cloud.GetInstance, - Args: cobra.ExactArgs(1), + Use: "get ", + Short: "Get a specific instance", + ValidArgsFunction: completion.CloudResources("/v1/cloud/project/%s/instance"), + Run: cloud.GetInstance, + Args: cobra.ExactArgs(1), }) instanceCmd.AddCommand(getInstanceCreationCmd()) instanceCmd.AddCommand(&cobra.Command{ - Use: "delete ", - Short: "Delete the given instance", - Run: cloud.DeleteInstance, - Args: cobra.ExactArgs(1), + Use: "delete ", + Short: "Delete the given instance", + ValidArgsFunction: completion.CloudResources("/v1/cloud/project/%s/instance"), + Run: cloud.DeleteInstance, + Args: cobra.ExactArgs(1), }) instanceCmd.AddCommand(&cobra.Command{ - Use: "set-name ", - Short: "Set the name of the given instance", - Run: cloud.SetInstanceName, - Args: cobra.ExactArgs(2), + Use: "set-name ", + Short: "Set the name of the given instance", + ValidArgsFunction: completion.CloudResources("/v1/cloud/project/%s/instance"), + Run: cloud.SetInstanceName, + Args: cobra.ExactArgs(2), }) instanceCmd.AddCommand(&cobra.Command{ - Use: "start ", - Short: "Start the given instance", - Run: cloud.StartInstance, - Args: cobra.ExactArgs(1), + Use: "start ", + Short: "Start the given instance", + ValidArgsFunction: completion.CloudResources("/v1/cloud/project/%s/instance"), + Run: cloud.StartInstance, + Args: cobra.ExactArgs(1), }) instanceCmd.AddCommand(&cobra.Command{ - Use: "stop ", - Short: "Stop the given instance", - Run: cloud.StopInstance, - Args: cobra.ExactArgs(1), + Use: "stop ", + Short: "Stop the given instance", + ValidArgsFunction: completion.CloudResources("/v1/cloud/project/%s/instance"), + Run: cloud.StopInstance, + Args: cobra.ExactArgs(1), }) instanceCmd.AddCommand(&cobra.Command{ @@ -199,8 +205,9 @@ func initInstanceCommand(cloudCmd *cobra.Command) { The data of the local storage will be stored, the duration of the operation depends on the size of the local disk. The instance can be unshelved at any time. Meanwhile hourly instances will not be billed. The Snapshot Storage used to store the instance's data will be billed.`, - Run: cloud.ShelveInstance, - Args: cobra.ExactArgs(1), + ValidArgsFunction: completion.CloudResources("/v1/cloud/project/%s/instance"), + Run: cloud.ShelveInstance, + Args: cobra.ExactArgs(1), }) instanceCmd.AddCommand(&cobra.Command{ @@ -209,22 +216,25 @@ The Snapshot Storage used to store the instance's data will be billed.`, Long: `The resources dedicated to the Public Cloud instance are restored. The duration of the operation depends on the size of the local disk. Instance billing will get back to normal and the snapshot used to store the instance's data will be deleted.`, - Run: cloud.UnshelveInstance, - Args: cobra.ExactArgs(1), + ValidArgsFunction: completion.CloudResources("/v1/cloud/project/%s/instance"), + Run: cloud.UnshelveInstance, + Args: cobra.ExactArgs(1), }) instanceCmd.AddCommand(&cobra.Command{ - Use: "resume ", - Short: "Resume the given suspended instance", - Run: cloud.ResumeInstance, - Args: cobra.ExactArgs(1), + Use: "resume ", + Short: "Resume the given suspended instance", + ValidArgsFunction: completion.CloudResources("/v1/cloud/project/%s/instance"), + Run: cloud.ResumeInstance, + Args: cobra.ExactArgs(1), }) rebootCmd := &cobra.Command{ - Use: "reboot ", - Short: "Reboot the given instance", - Run: cloud.RebootInstance, - Args: cobra.ExactArgs(1), + Use: "reboot ", + Short: "Reboot the given instance", + ValidArgsFunction: completion.CloudResources("/v1/cloud/project/%s/instance"), + Run: cloud.RebootInstance, + Args: cobra.ExactArgs(1), } rebootCmd.Flags().StringVarP(&cloud.InstanceRebootType, "type", "t", "soft", "Reboot type: hard or soft (default is soft)") instanceCmd.AddCommand(rebootCmd) @@ -275,8 +285,9 @@ There are three ways to define the installation parameters: ovhcloud cloud instance reinstall c7e272d4-4c11-11f0-bf07-0050568ce122 --editor --image `, - Run: cloud.ReinstallInstance, - Args: cobra.MaximumNArgs(1), + ValidArgsFunction: completion.CloudResources("/v1/cloud/project/%s/instance"), + Run: cloud.ReinstallInstance, + Args: cobra.MaximumNArgs(1), } addParameterFileFlags(reinstallCmd, false, assets.CloudOpenapiSchema, "/cloud/project/{serviceName}/instance/{instanceId}/reinstall", "post", "", nil) addInteractiveEditorFlag(reinstallCmd) @@ -289,10 +300,11 @@ There are three ways to define the installation parameters: instanceCmd.AddCommand(reinstallCmd) instanceCmd.AddCommand(&cobra.Command{ - Use: "activate-monthly-billing ", - Short: "Activate monthly billing for the given instance", - Run: cloud.ActivateMonthlyBilling, - Args: cobra.ExactArgs(1), + Use: "activate-monthly-billing ", + Short: "Activate monthly billing for the given instance", + ValidArgsFunction: completion.CloudResources("/v1/cloud/project/%s/instance"), + Run: cloud.ActivateMonthlyBilling, + Args: cobra.ExactArgs(1), }) interfacesCommand := &cobra.Command{ @@ -302,58 +314,65 @@ There are three ways to define the installation parameters: instanceCmd.AddCommand(interfacesCommand) interfacesCommand.AddCommand(withFilterFlag(&cobra.Command{ - Use: "list ", - Aliases: []string{"ls"}, - Short: "List interfaces of the given instance", - Run: cloud.ListInstanceInterfaces, - Args: cobra.ExactArgs(1), + Use: "list ", + Aliases: []string{"ls"}, + Short: "List interfaces of the given instance", + ValidArgsFunction: completion.CloudResources("/v1/cloud/project/%s/instance"), + Run: cloud.ListInstanceInterfaces, + Args: cobra.ExactArgs(1), })) interfacesCommand.AddCommand(&cobra.Command{ - Use: "get ", - Short: "Get a specific interface of the given instance", - Run: cloud.GetInstanceInterface, - Args: cobra.ExactArgs(2), + Use: "get ", + Short: "Get a specific interface of the given instance", + ValidArgsFunction: completion.CloudResources("/v1/cloud/project/%s/instance"), + Run: cloud.GetInstanceInterface, + Args: cobra.ExactArgs(2), }) interfacesCommand.AddCommand(&cobra.Command{ - Use: "create ", - Short: "Create interface on the given instance and attach it to a network", - Run: cloud.CreateInstanceInterface, - Args: cobra.RangeArgs(2, 3), + Use: "create ", + Short: "Create interface on the given instance and attach it to a network", + ValidArgsFunction: completion.CloudResources("/v1/cloud/project/%s/instance"), + Run: cloud.CreateInstanceInterface, + Args: cobra.RangeArgs(2, 3), }) interfacesCommand.AddCommand(&cobra.Command{ - Use: "delete ", - Short: "Delete a specific interface of the given instance", - Run: cloud.DeleteInstanceInterface, - Args: cobra.ExactArgs(2), + Use: "delete ", + Short: "Delete a specific interface of the given instance", + ValidArgsFunction: completion.CloudResources("/v1/cloud/project/%s/instance"), + Run: cloud.DeleteInstanceInterface, + Args: cobra.ExactArgs(2), }) enableRescueCmd := &cobra.Command{ - Use: "reboot-rescue ", - Short: "Reboot the given instance in rescue mode", - Run: cloud.EnableInstanceInRescueMode, - Args: cobra.ExactArgs(1), + Use: "reboot-rescue ", + Short: "Reboot the given instance in rescue mode", + ValidArgsFunction: completion.CloudResources("/v1/cloud/project/%s/instance"), + Run: cloud.EnableInstanceInRescueMode, + Args: cobra.ExactArgs(1), } enableRescueCmd.Flags().StringVar(&cloud.InstanceImageID, "image", "", "Image to boot from") enableRescueCmd.Flags().BoolVar(&flags.WaitForTask, "wait", false, "Wait for instance to be in rescue mode before exiting") instanceCmd.AddCommand(enableRescueCmd) disableRescueCmd := &cobra.Command{ - Use: "exit-rescue ", - Short: "Exit the given instance from rescue mode", - Run: cloud.DisableInstanceRescueMode, - Args: cobra.ExactArgs(1), + Use: "exit-rescue ", + Short: "Exit the given instance from rescue mode", + ValidArgsFunction: completion.CloudResources("/v1/cloud/project/%s/instance"), + Run: cloud.DisableInstanceRescueMode, + Args: cobra.ExactArgs(1), } disableRescueCmd.Flags().BoolVar(&flags.WaitForTask, "wait", false, "Wait for instance to have exited rescue mode before exiting") instanceCmd.AddCommand(disableRescueCmd) setFlavorCmd := &cobra.Command{ - Use: "set-flavor ", - Short: "Migrate the given instance to the specified flavor", - Run: cloud.SetInstanceFlavor, - Args: cobra.RangeArgs(1, 2), + Use: "set-flavor ", + Short: "Migrate the given instance to the specified flavor", + ValidArgsFunction: completion.CloudResources("/v1/cloud/project/%s/instance"), + Run: cloud.SetInstanceFlavor, + Args: cobra.RangeArgs(1, 2), } setFlavorCmd.Flags().BoolVar(&flags.WaitForTask, "wait", false, "Wait for instance to run with the desired flavor before exiting") setFlavorCmd.Flags().BoolVar(&cloud.InstanceFlavorViaInteractiveSelector, "flavor-selector", false, "Use the interactive flavor selector") @@ -366,10 +385,11 @@ There are three ways to define the installation parameters: instanceCmd.AddCommand(backupCmd) backupCreateCmd := &cobra.Command{ - Use: "create ", - Short: "Create a backup of the given instance", - Run: cloud.CreateInstanceBackup, - Args: cobra.ExactArgs(2), + Use: "create ", + Short: "Create a backup of the given instance", + ValidArgsFunction: completion.CloudResources("/v1/cloud/project/%s/instance"), + Run: cloud.CreateInstanceBackup, + Args: cobra.ExactArgs(2), } backupCreateCmd.Flags().StringVar(&cloud.InstanceBackupSpec.DistantSnapshotName, "distant-backup-name", "", "Name of the backup in the distant region (for cross region backup)") backupCreateCmd.Flags().StringVar(&cloud.InstanceBackupSpec.DistantRegionName, "distant-region-name", "", "Name of the distant region (for cross region backup)") @@ -377,10 +397,11 @@ There are three ways to define the installation parameters: backupCmd.AddCommand(backupCreateCmd) backupCmd.AddCommand(&cobra.Command{ - Use: "abort ", - Short: "Abort the backup creation of the given instance", - Run: cloud.AbortInstanceBackup, - Args: cobra.ExactArgs(1), + Use: "abort ", + Short: "Abort the backup creation of the given instance", + ValidArgsFunction: completion.CloudResources("/v1/cloud/project/%s/instance"), + Run: cloud.AbortInstanceBackup, + Args: cobra.ExactArgs(1), }) backupCmd.AddCommand(withFilterFlag(&cobra.Command{ @@ -421,10 +442,11 @@ There are three ways to define the installation parameters: })) groupCmd.AddCommand(&cobra.Command{ - Use: "get ", - Short: "Get a specific instance group", - Run: cloud.GetInstanceGroup, - Args: cobra.ExactArgs(1), + Use: "get ", + Short: "Get a specific instance group", + ValidArgsFunction: completion.CloudResources("/v1/cloud/project/%s/instance/group"), + Run: cloud.GetInstanceGroup, + Args: cobra.ExactArgs(1), }) createGroupCmd := &cobra.Command{ @@ -437,10 +459,11 @@ There are three ways to define the installation parameters: groupCmd.AddCommand(createGroupCmd) groupCmd.AddCommand(&cobra.Command{ - Use: "delete ", - Short: "Delete a specific instance group", - Run: cloud.DeleteInstanceGroup, - Args: cobra.ExactArgs(1), + Use: "delete ", + Short: "Delete a specific instance group", + ValidArgsFunction: completion.CloudResources("/v1/cloud/project/%s/instance/group"), + Run: cloud.DeleteInstanceGroup, + Args: cobra.ExactArgs(1), }) // Autobackup subcommands @@ -451,25 +474,28 @@ There are three ways to define the installation parameters: instanceCmd.AddCommand(autobackupCmd) autobackupCmd.AddCommand(withFilterFlag(&cobra.Command{ - Use: "list ", - Aliases: []string{"ls"}, - Short: "List automatic backup workflows for the given instance", - Run: cloud.ListAutobackups, - Args: cobra.ExactArgs(1), + Use: "list ", + Aliases: []string{"ls"}, + Short: "List automatic backup workflows for the given instance", + ValidArgsFunction: completion.CloudResources("/v1/cloud/project/%s/instance"), + Run: cloud.ListAutobackups, + Args: cobra.ExactArgs(1), })) autobackupCmd.AddCommand(&cobra.Command{ - Use: "get ", - Short: "Get details of an automatic backup workflow", - Run: cloud.GetAutobackup, - Args: cobra.ExactArgs(2), + Use: "get ", + Short: "Get details of an automatic backup workflow", + ValidArgsFunction: completion.CloudResources("/v1/cloud/project/%s/instance"), + Run: cloud.GetAutobackup, + Args: cobra.ExactArgs(2), }) createAutobackupCmd := &cobra.Command{ - Use: "create ", - Short: "Create an automatic backup workflow for the given instance", - Run: cloud.CreateAutobackup, - Args: cobra.ExactArgs(1), + Use: "create ", + Short: "Create an automatic backup workflow for the given instance", + ValidArgsFunction: completion.CloudResources("/v1/cloud/project/%s/instance"), + Run: cloud.CreateAutobackup, + Args: cobra.ExactArgs(1), } createAutobackupCmd.Flags().StringVar(&cloud.AutobackupCreateParams.Cron, "cron", "", "Unix Cron pattern (e.g. '0 0 * * *')") createAutobackupCmd.Flags().IntVar(&cloud.AutobackupCreateParams.Rotation, "rotation", 0, "Number of backups to keep") @@ -480,19 +506,21 @@ There are three ways to define the installation parameters: autobackupCmd.AddCommand(createAutobackupCmd) autobackupCmd.AddCommand(&cobra.Command{ - Use: "delete ", - Short: "Delete an automatic backup workflow", - Run: cloud.DeleteAutobackup, - Args: cobra.ExactArgs(2), + Use: "delete ", + Short: "Delete an automatic backup workflow", + ValidArgsFunction: completion.CloudResources("/v1/cloud/project/%s/instance"), + Run: cloud.DeleteAutobackup, + Args: cobra.ExactArgs(2), }) // Application access subcommand instanceCmd.AddCommand(&cobra.Command{ - Use: "application-access ", - Short: "Get application access credentials for the given instance", - Long: `Get the credentials to access the application installed on the given instance (e.g. WordPress, GitLab, etc.)`, - Run: cloud.GetInstanceApplicationAccess, - Args: cobra.ExactArgs(1), + Use: "application-access ", + Short: "Get application access credentials for the given instance", + Long: `Get the credentials to access the application installed on the given instance (e.g. WordPress, GitLab, etc.)`, + ValidArgsFunction: completion.CloudResources("/v1/cloud/project/%s/instance"), + Run: cloud.GetInstanceApplicationAccess, + Args: cobra.ExactArgs(1), }) cloudCmd.AddCommand(instanceCmd) diff --git a/internal/cmd/cloud_ip.go b/internal/cmd/cloud_ip.go index 1e82fdef..37b83ae5 100644 --- a/internal/cmd/cloud_ip.go +++ b/internal/cmd/cloud_ip.go @@ -7,6 +7,7 @@ package cmd import ( "fmt" + "github.com/ovh/ovhcloud-cli/internal/completion" "github.com/ovh/ovhcloud-cli/internal/services/cloud" "github.com/spf13/cobra" ) @@ -76,6 +77,7 @@ func initCloudIPCommand(cloudCmd *cobra.Command) { PreRunE: func(_ *cobra.Command, _ []string) error { return validateCloudIPType(cloudIPTypeFloating, cloudIPTypeFailover) }, + ValidArgsFunction: completion.CloudResources("/v1/cloud/project/%s/ip"), Run: func(cmd *cobra.Command, args []string) { switch cloudIPType { case cloudIPTypeFloating: @@ -94,7 +96,8 @@ func initCloudIPCommand(cloudCmd *cobra.Command) { PreRunE: func(_ *cobra.Command, _ []string) error { return validateCloudIPType(cloudIPTypeFloating) }, - Run: cloud.DeleteFloatingIP, + ValidArgsFunction: completion.CloudResources("/v1/cloud/project/%s/ip"), + Run: cloud.DeleteFloatingIP, }) // attach (failover only) @@ -105,7 +108,8 @@ func initCloudIPCommand(cloudCmd *cobra.Command) { PreRunE: func(_ *cobra.Command, _ []string) error { return validateCloudIPType(cloudIPTypeFailover) }, - Run: cloud.AttachCloudIPFailover, + ValidArgsFunction: completion.CloudResources("/v1/cloud/project/%s/ip"), + Run: cloud.AttachCloudIPFailover, }) cloudCmd.AddCommand(ipCmd) diff --git a/internal/cmd/cloud_managed_database.go b/internal/cmd/cloud_managed_database.go index d4c9dad5..0af8e1f0 100644 --- a/internal/cmd/cloud_managed_database.go +++ b/internal/cmd/cloud_managed_database.go @@ -5,6 +5,7 @@ package cmd import ( + "github.com/ovh/ovhcloud-cli/internal/completion" "github.com/ovh/ovhcloud-cli/internal/services/cloud" "github.com/spf13/cobra" ) @@ -25,20 +26,22 @@ func initManagedDatabaseCommand(cloudCmd *cobra.Command) { })) managedDatabaseCmd.AddCommand(&cobra.Command{ - Use: "get ", - Short: "Get a specific managed database service", - Run: cloud.GetManagedDatabase, - Args: cobra.ExactArgs(1), + Use: "get ", + Short: "Get a specific managed database service", + ValidArgsFunction: completion.CloudResources("/v1/cloud/project/%s/database"), + Run: cloud.GetManagedDatabase, + Args: cobra.ExactArgs(1), }) managedDatabaseCmd.AddCommand(managedDatabaseCreationCmd()) managedDatabaseCmd.AddCommand(managedDatabaseEditCmd()) managedDatabaseCmd.AddCommand(&cobra.Command{ - Use: "delete ", - Short: "Delete a specific managed database service", - Run: cloud.DeleteManagedDatabase, - Args: cobra.ExactArgs(1), + Use: "delete ", + Short: "Delete a specific managed database service", + ValidArgsFunction: completion.CloudResources("/v1/cloud/project/%s/database"), + Run: cloud.DeleteManagedDatabase, + Args: cobra.ExactArgs(1), }) initManagedDatabaseDatabaseCommand(managedDatabaseCmd) @@ -57,27 +60,30 @@ func initManagedDatabaseDatabaseCommand(managedDatabaseCmd *cobra.Command) { } databaseCmd.AddCommand(withFilterFlag(&cobra.Command{ - Use: "list ", - Aliases: []string{"ls"}, - Short: "List all databases in the given managed database service", - Run: cloud.ListManagedDatabaseDatabases, - Args: cobra.ExactArgs(1), + Use: "list ", + Aliases: []string{"ls"}, + Short: "List all databases in the given managed database service", + ValidArgsFunction: completion.CloudResources("/v1/cloud/project/%s/database"), + Run: cloud.ListManagedDatabaseDatabases, + Args: cobra.ExactArgs(1), })) databaseCmd.AddCommand(&cobra.Command{ - Use: "get ", - Short: "Get a specific database in the given managed database service", - Run: cloud.GetManagedDatabaseDatabase, - Args: cobra.ExactArgs(2), + Use: "get ", + Short: "Get a specific database in the given managed database service", + ValidArgsFunction: completion.CloudResources("/v1/cloud/project/%s/database"), + Run: cloud.GetManagedDatabaseDatabase, + Args: cobra.ExactArgs(2), }) databaseCmd.AddCommand(managedDatabaseDatabaseCreateCmd()) databaseCmd.AddCommand(&cobra.Command{ - Use: "delete ", - Short: "Delete a specific database in the given managed database service", - Run: cloud.DeleteManagedDatabaseDatabase, - Args: cobra.ExactArgs(2), + Use: "delete ", + Short: "Delete a specific database in the given managed database service", + ValidArgsFunction: completion.CloudResources("/v1/cloud/project/%s/database"), + Run: cloud.DeleteManagedDatabaseDatabase, + Args: cobra.ExactArgs(2), }) managedDatabaseCmd.AddCommand(databaseCmd) @@ -90,35 +96,39 @@ func initManagedDatabaseUserCommand(managedDatabaseCmd *cobra.Command) { } userCmd.AddCommand(withFilterFlag(&cobra.Command{ - Use: "list ", - Aliases: []string{"ls"}, - Short: "List all users in the given managed database service", - Run: cloud.ListManagedDatabaseUsers, - Args: cobra.ExactArgs(1), + Use: "list ", + Aliases: []string{"ls"}, + Short: "List all users in the given managed database service", + ValidArgsFunction: completion.CloudResources("/v1/cloud/project/%s/database"), + Run: cloud.ListManagedDatabaseUsers, + Args: cobra.ExactArgs(1), })) userCmd.AddCommand(&cobra.Command{ - Use: "get ", - Short: "Get a specific user in the given managed database service", - Run: cloud.GetManagedDatabaseUser, - Args: cobra.ExactArgs(2), + Use: "get ", + Short: "Get a specific user in the given managed database service", + ValidArgsFunction: completion.CloudResources("/v1/cloud/project/%s/database"), + Run: cloud.GetManagedDatabaseUser, + Args: cobra.ExactArgs(2), }) userCmd.AddCommand(managedDatabaseUserCreateCmd()) userCmd.AddCommand(managedDatabaseUserEditCmd()) userCmd.AddCommand(&cobra.Command{ - Use: "delete ", - Short: "Delete a specific user in the given managed database service", - Run: cloud.DeleteManagedDatabaseUser, - Args: cobra.ExactArgs(2), + Use: "delete ", + Short: "Delete a specific user in the given managed database service", + ValidArgsFunction: completion.CloudResources("/v1/cloud/project/%s/database"), + Run: cloud.DeleteManagedDatabaseUser, + Args: cobra.ExactArgs(2), }) userCmd.AddCommand(&cobra.Command{ - Use: "credentials-reset ", - Short: "Reset the credentials of a specific user in the given managed database service", - Run: cloud.ResetManagedDatabaseUserCredentials, - Args: cobra.ExactArgs(2), + Use: "credentials-reset ", + Short: "Reset the credentials of a specific user in the given managed database service", + ValidArgsFunction: completion.CloudResources("/v1/cloud/project/%s/database"), + Run: cloud.ResetManagedDatabaseUserCredentials, + Args: cobra.ExactArgs(2), }) managedDatabaseCmd.AddCommand(userCmd) @@ -142,10 +152,11 @@ func initManagedDatabaseCertificateCommand(managedDatabaseCmd *cobra.Command) { } certificateCmd.AddCommand(&cobra.Command{ - Use: "get ", - Short: "Get certificates in the given managed database service", - Run: cloud.GetManagedDatabaseCertificates, - Args: cobra.ExactArgs(1), + Use: "get ", + Short: "Get certificates in the given managed database service", + ValidArgsFunction: completion.CloudResources("/v1/cloud/project/%s/database"), + Run: cloud.GetManagedDatabaseCertificates, + Args: cobra.ExactArgs(1), }) managedDatabaseCmd.AddCommand(certificateCmd) @@ -158,25 +169,28 @@ func initManagedDatabaseBackupCommand(managedDatabaseCmd *cobra.Command) { } backupCmd.AddCommand(withFilterFlag(&cobra.Command{ - Use: "list ", - Aliases: []string{"ls"}, - Short: "List all backups in the given managed database service", - Run: cloud.ListManagedDatabaseBackups, - Args: cobra.ExactArgs(1), + Use: "list ", + Aliases: []string{"ls"}, + Short: "List all backups in the given managed database service", + ValidArgsFunction: completion.CloudResources("/v1/cloud/project/%s/database"), + Run: cloud.ListManagedDatabaseBackups, + Args: cobra.ExactArgs(1), })) backupCmd.AddCommand(&cobra.Command{ - Use: "get ", - Short: "Get a specific backup in the given managed database service", - Run: cloud.GetManagedDatabaseBackup, - Args: cobra.ExactArgs(2), + Use: "get ", + Short: "Get a specific backup in the given managed database service", + ValidArgsFunction: completion.CloudResources("/v1/cloud/project/%s/database"), + Run: cloud.GetManagedDatabaseBackup, + Args: cobra.ExactArgs(2), }) backupCmd.AddCommand(&cobra.Command{ - Use: "restore ", - Short: "Restore a specific backup in the given managed database service", - Run: cloud.RestoreManagedDatabaseBackup, - Args: cobra.ExactArgs(2), + Use: "restore ", + Short: "Restore a specific backup in the given managed database service", + ValidArgsFunction: completion.CloudResources("/v1/cloud/project/%s/database"), + Run: cloud.RestoreManagedDatabaseBackup, + Args: cobra.ExactArgs(2), }) managedDatabaseCmd.AddCommand(backupCmd) @@ -267,8 +281,9 @@ There are two ways to define the edition parameters: ovhcloud cloud managed-database edit --editor --description "My database cluster" `, - Run: cloud.EditManagedDatabase, - Args: cobra.ExactArgs(1), + ValidArgsFunction: completion.CloudResources("/v1/cloud/project/%s/database"), + Run: cloud.EditManagedDatabase, + Args: cobra.ExactArgs(1), } // Database details @@ -299,8 +314,9 @@ func managedDatabaseDatabaseCreateCmd() *cobra.Command { ovhcloud cloud managed-database database create --name mydb `, - Run: cloud.CreateManagedDatabaseDatabase, - Args: cobra.ExactArgs(1), + ValidArgsFunction: completion.CloudResources("/v1/cloud/project/%s/database"), + Run: cloud.CreateManagedDatabaseDatabase, + Args: cobra.ExactArgs(1), } databaseCreateCmd.Flags().StringVar(&cloud.ManagedDatabaseDatabaseSpec.Name, "name", "", "Name of the database to create") @@ -338,8 +354,9 @@ There are two ways to define the creation parameters: ovhcloud cloud managed-database user create --name myuser --editor --roles role1,role2 `, - Run: cloud.CreateManagedDatabaseUser, - Args: cobra.ExactArgs(1), + ValidArgsFunction: completion.CloudResources("/v1/cloud/project/%s/database"), + Run: cloud.CreateManagedDatabaseUser, + Args: cobra.ExactArgs(1), } userCreateCmd.Flags().StringVar(&cloud.ManagedDatabaseUserSpec.Name, "name", "", "Name of the user to create") @@ -385,8 +402,9 @@ There are two ways to define the edition parameters: ovhcloud cloud managed-database user edit --editor --roles role1,role2 `, - Run: cloud.EditManagedDatabaseUser, - Args: cobra.ExactArgs(2), + ValidArgsFunction: completion.CloudResources("/v1/cloud/project/%s/database"), + Run: cloud.EditManagedDatabaseUser, + Args: cobra.ExactArgs(2), } // PostgreSQL and MongoDB specific flags @@ -405,11 +423,12 @@ There are two ways to define the edition parameters: func managedDatabaseRoleListCmd() *cobra.Command { roleListCmd := &cobra.Command{ - Use: "list ", - Aliases: []string{"ls"}, - Short: "List roles in the given managed database service", - Run: cloud.ListManagedDatabaseRoles, - Args: cobra.ExactArgs(1), + Use: "list ", + Aliases: []string{"ls"}, + Short: "List roles in the given managed database service", + ValidArgsFunction: completion.CloudResources("/v1/cloud/project/%s/database"), + Run: cloud.ListManagedDatabaseRoles, + Args: cobra.ExactArgs(1), } // MongoDB specific flags diff --git a/internal/cmd/cloud_managed_kubernetes.go b/internal/cmd/cloud_managed_kubernetes.go index a8a0067f..cca9c74e 100644 --- a/internal/cmd/cloud_managed_kubernetes.go +++ b/internal/cmd/cloud_managed_kubernetes.go @@ -8,6 +8,7 @@ import ( "runtime" "github.com/ovh/ovhcloud-cli/internal/assets" + "github.com/ovh/ovhcloud-cli/internal/completion" "github.com/ovh/ovhcloud-cli/internal/flags" "github.com/ovh/ovhcloud-cli/internal/services/cloud" "github.com/spf13/cobra" @@ -31,19 +32,21 @@ func initKubeCommand(cloudCmd *cobra.Command) { kubeCmd.AddCommand(withFilterFlag(kubeListCmd)) kubeCmd.AddCommand(&cobra.Command{ - Use: "get ", - Short: "Get the given Kubernetes cluster", - Run: cloud.GetKube, - Args: cobra.ExactArgs(1), + Use: "get ", + Short: "Get the given Kubernetes cluster", + ValidArgsFunction: completion.CloudResources("/v1/cloud/project/%s/kube"), + Run: cloud.GetKube, + Args: cobra.ExactArgs(1), }) kubeCmd.AddCommand(getKubeCreateCmd()) kubeEditCmd := &cobra.Command{ - Use: "edit ", - Short: "Edit the given Kubernetes cluster", - Run: cloud.EditKube, - Args: cobra.ExactArgs(1), + Use: "edit ", + Short: "Edit the given Kubernetes cluster", + ValidArgsFunction: completion.CloudResources("/v1/cloud/project/%s/kube"), + Run: cloud.EditKube, + Args: cobra.ExactArgs(1), } kubeEditCmd.Flags().StringVar(&cloud.KubeSpec.Name, "name", "", "Name of the Kubernetes cluster") kubeEditCmd.Flags().StringVar(&cloud.KubeSpec.UpdatePolicy, "update-policy", "", "Update policy for the cluster (ALWAYS_UPDATE, MINIMAL_DOWNTIME, NEVER_UPDATE)") @@ -51,10 +54,11 @@ func initKubeCommand(cloudCmd *cobra.Command) { kubeCmd.AddCommand(kubeEditCmd) kubeCmd.AddCommand(&cobra.Command{ - Use: "delete ", - Short: "Delete the given Kubernetes cluster", - Run: cloud.DeleteKube, - Args: cobra.ExactArgs(1), + Use: "delete ", + Short: "Delete the given Kubernetes cluster", + ValidArgsFunction: completion.CloudResources("/v1/cloud/project/%s/kube"), + Run: cloud.DeleteKube, + Args: cobra.ExactArgs(1), }) customizationCmd := &cobra.Command{ @@ -64,17 +68,19 @@ func initKubeCommand(cloudCmd *cobra.Command) { kubeCmd.AddCommand(customizationCmd) customizationCmd.AddCommand(&cobra.Command{ - Use: "get ", - Short: "Get the customization of the given Kubernetes cluster", - Run: cloud.GetKubeCustomization, - Args: cobra.ExactArgs(1), + Use: "get ", + Short: "Get the customization of the given Kubernetes cluster", + ValidArgsFunction: completion.CloudResources("/v1/cloud/project/%s/kube"), + Run: cloud.GetKubeCustomization, + Args: cobra.ExactArgs(1), }) customizationEditCmd := &cobra.Command{ - Use: "edit ", - Short: "Edit the customization of the given Kubernetes cluster", - Run: cloud.EditKubeCustomization, - Args: cobra.ExactArgs(1), + Use: "edit ", + Short: "Edit the customization of the given Kubernetes cluster", + ValidArgsFunction: completion.CloudResources("/v1/cloud/project/%s/kube"), + Run: cloud.EditKubeCustomization, + Args: cobra.ExactArgs(1), } customizationEditCmd.Flags().StringSliceVar(&cloud.KubeSpec.Customization.APIServer.AdmissionPlugins.Enabled, "api-server.admission-plugins.enabled", nil, "Admission plugins to enable on API server (AlwaysPullImages, NodeRestriction)") customizationEditCmd.Flags().StringSliceVar(&cloud.KubeSpec.Customization.APIServer.AdmissionPlugins.Disabled, "api-server.admission-plugins.disabled", nil, "Admission plugins to disable on API server (AlwaysPullImages, NodeRestriction)") @@ -96,18 +102,20 @@ func initKubeCommand(cloudCmd *cobra.Command) { kubeCmd.AddCommand(ipRestrictionsCmd) ipRestrictionsCmd.AddCommand(withFilterFlag(&cobra.Command{ - Use: "list ", - Aliases: []string{"ls"}, - Short: "List IP restrictions for the given Kubernetes cluster", - Run: cloud.ListKubeIPRestrictions, - Args: cobra.ExactArgs(1), + Use: "list ", + Aliases: []string{"ls"}, + Short: "List IP restrictions for the given Kubernetes cluster", + ValidArgsFunction: completion.CloudResources("/v1/cloud/project/%s/kube"), + Run: cloud.ListKubeIPRestrictions, + Args: cobra.ExactArgs(1), })) ipRestrictionsEditCmd := &cobra.Command{ - Use: "edit ", - Short: "Edit IP restrictions for the given Kubernetes cluster", - Run: cloud.EditKubeIPRestrictions, - Args: cobra.ExactArgs(1), + Use: "edit ", + Short: "Edit IP restrictions for the given Kubernetes cluster", + ValidArgsFunction: completion.CloudResources("/v1/cloud/project/%s/kube"), + Run: cloud.EditKubeIPRestrictions, + Args: cobra.ExactArgs(1), } ipRestrictionsEditCmd.Flags().StringSliceVar(&cloud.KubeIPRestrictions, "ips", nil, "List of IPs to restrict access to the Kubernetes cluster") addInteractiveEditorFlag(ipRestrictionsEditCmd) @@ -121,17 +129,19 @@ func initKubeCommand(cloudCmd *cobra.Command) { kubeCmd.AddCommand(kubeConfigCmd) kubeConfigCmd.AddCommand(&cobra.Command{ - Use: "generate ", - Short: "Generate the kubeconfig for the given Kubernetes cluster", - Run: cloud.GenerateKubeConfig, - Args: cobra.ExactArgs(1), + Use: "generate ", + Short: "Generate the kubeconfig for the given Kubernetes cluster", + ValidArgsFunction: completion.CloudResources("/v1/cloud/project/%s/kube"), + Run: cloud.GenerateKubeConfig, + Args: cobra.ExactArgs(1), }) kubeConfigCmd.AddCommand(&cobra.Command{ - Use: "reset ", - Short: "Reset the kubeconfig for the given Kubernetes cluster. Certificates will be regenerated and nodes will be reinstalled", - Run: cloud.ResetKubeConfig, - Args: cobra.ExactArgs(1), + Use: "reset ", + Short: "Reset the kubeconfig for the given Kubernetes cluster. Certificates will be regenerated and nodes will be reinstalled", + ValidArgsFunction: completion.CloudResources("/v1/cloud/project/%s/kube"), + Run: cloud.ResetKubeConfig, + Args: cobra.ExactArgs(1), }) nodeCmd := &cobra.Command{ @@ -141,25 +151,28 @@ func initKubeCommand(cloudCmd *cobra.Command) { kubeCmd.AddCommand(nodeCmd) nodeCmd.AddCommand(withFilterFlag(&cobra.Command{ - Use: "list ", - Aliases: []string{"ls"}, - Short: "List nodes in the given Kubernetes cluster", - Run: cloud.ListKubeNodes, - Args: cobra.ExactArgs(1), + Use: "list ", + Aliases: []string{"ls"}, + Short: "List nodes in the given Kubernetes cluster", + ValidArgsFunction: completion.CloudResources("/v1/cloud/project/%s/kube"), + Run: cloud.ListKubeNodes, + Args: cobra.ExactArgs(1), })) nodeCmd.AddCommand(&cobra.Command{ - Use: "get ", - Short: "Get the given Kubernetes node", - Run: cloud.GetKubeNode, - Args: cobra.ExactArgs(2), + Use: "get ", + Short: "Get the given Kubernetes node", + ValidArgsFunction: completion.CloudResourceWithChild("/v1/cloud/project/%s/kube", "/v1/cloud/project/%s/kube/%s/node"), + Run: cloud.GetKubeNode, + Args: cobra.ExactArgs(2), }) nodeCmd.AddCommand(&cobra.Command{ - Use: "delete ", - Short: "Delete the given Kubernetes node", - Run: cloud.DeleteKubeNode, - Args: cobra.ExactArgs(2), + Use: "delete ", + Short: "Delete the given Kubernetes node", + ValidArgsFunction: completion.CloudResourceWithChild("/v1/cloud/project/%s/kube", "/v1/cloud/project/%s/kube/%s/node"), + Run: cloud.DeleteKubeNode, + Args: cobra.ExactArgs(2), }) nodepoolCmd := &cobra.Command{ @@ -169,27 +182,30 @@ func initKubeCommand(cloudCmd *cobra.Command) { kubeCmd.AddCommand(nodepoolCmd) nodepoolCmd.AddCommand(withFilterFlag(&cobra.Command{ - Use: "list ", - Aliases: []string{"ls"}, - Short: "List node pools in the given Kubernetes cluster", - Run: cloud.ListKubeNodepools, - Args: cobra.ExactArgs(1), + Use: "list ", + Aliases: []string{"ls"}, + Short: "List node pools in the given Kubernetes cluster", + ValidArgsFunction: completion.CloudResources("/v1/cloud/project/%s/kube"), + Run: cloud.ListKubeNodepools, + Args: cobra.ExactArgs(1), })) nodepoolCmd.AddCommand(&cobra.Command{ - Use: "get ", - Short: "Get the given Kubernetes node pool", - Run: cloud.GetKubeNodepool, - Args: cobra.ExactArgs(2), + Use: "get ", + Short: "Get the given Kubernetes node pool", + ValidArgsFunction: completion.CloudResourceWithChild("/v1/cloud/project/%s/kube", "/v1/cloud/project/%s/kube/%s/nodepool"), + Run: cloud.GetKubeNodepool, + Args: cobra.ExactArgs(2), }) nodepoolCmd.AddCommand(getNodepoolEditCmd()) nodepoolCmd.AddCommand(&cobra.Command{ - Use: "delete ", - Short: "Delete the given Kubernetes node pool", - Run: cloud.DeleteKubeNodepool, - Args: cobra.ExactArgs(2), + Use: "delete ", + Short: "Delete the given Kubernetes node pool", + ValidArgsFunction: completion.CloudResourceWithChild("/v1/cloud/project/%s/kube", "/v1/cloud/project/%s/kube/%s/nodepool"), + Run: cloud.DeleteKubeNodepool, + Args: cobra.ExactArgs(2), }) nodepoolCmd.AddCommand(getKubeNodePoolCreateCmd()) @@ -201,17 +217,19 @@ func initKubeCommand(cloudCmd *cobra.Command) { kubeCmd.AddCommand(oidcCmd) oidcCmd.AddCommand(&cobra.Command{ - Use: "get ", - Short: "Get the OIDC configuration for the given Kubernetes cluster", - Run: cloud.GetKubeOIDCIntegration, - Args: cobra.ExactArgs(1), + Use: "get ", + Short: "Get the OIDC configuration for the given Kubernetes cluster", + ValidArgsFunction: completion.CloudResources("/v1/cloud/project/%s/kube"), + Run: cloud.GetKubeOIDCIntegration, + Args: cobra.ExactArgs(1), }) editCmd := &cobra.Command{ - Use: "edit ", - Short: "Edit the OIDC configuration for the given Kubernetes cluster", - Run: cloud.EditKubeOIDCIntegration, - Args: cobra.ExactArgs(1), + Use: "edit ", + Short: "Edit the OIDC configuration for the given Kubernetes cluster", + ValidArgsFunction: completion.CloudResources("/v1/cloud/project/%s/kube"), + Run: cloud.EditKubeOIDCIntegration, + Args: cobra.ExactArgs(1), } editCmd.Flags().StringVar(&cloud.KubeOIDCConfig.CaContent, "ca-content", "", "CA certificate content for the OIDC provider") editCmd.Flags().StringVar(&cloud.KubeOIDCConfig.ClientId, "client-id", "", "OIDC client ID") @@ -227,10 +245,11 @@ func initKubeCommand(cloudCmd *cobra.Command) { oidcCmd.AddCommand(getKubeOIDCCreateCmd()) oidcCmd.AddCommand(&cobra.Command{ - Use: "delete ", - Short: "Delete the OIDC integration for the given Kubernetes cluster", - Run: cloud.DeleteKubeOIDCIntegration, - Args: cobra.ExactArgs(1), + Use: "delete ", + Short: "Delete the OIDC integration for the given Kubernetes cluster", + ValidArgsFunction: completion.CloudResources("/v1/cloud/project/%s/kube"), + Run: cloud.DeleteKubeOIDCIntegration, + Args: cobra.ExactArgs(1), }) privateNetworkConfigCmd := &cobra.Command{ @@ -240,17 +259,19 @@ func initKubeCommand(cloudCmd *cobra.Command) { kubeCmd.AddCommand(privateNetworkConfigCmd) privateNetworkConfigCmd.AddCommand(&cobra.Command{ - Use: "get ", - Short: "Get the private network configuration for the given Kubernetes cluster", - Run: cloud.GetKubePrivateNetworkConfiguration, - Args: cobra.ExactArgs(1), + Use: "get ", + Short: "Get the private network configuration for the given Kubernetes cluster", + ValidArgsFunction: completion.CloudResources("/v1/cloud/project/%s/kube"), + Run: cloud.GetKubePrivateNetworkConfiguration, + Args: cobra.ExactArgs(1), }) privateNetworkConfigEditCmd := &cobra.Command{ - Use: "edit ", - Short: "Edit the private network configuration for the given Kubernetes cluster", - Run: cloud.EditKubePrivateNetworkConfiguration, - Args: cobra.ExactArgs(1), + Use: "edit ", + Short: "Edit the private network configuration for the given Kubernetes cluster", + ValidArgsFunction: completion.CloudResources("/v1/cloud/project/%s/kube"), + Run: cloud.EditKubePrivateNetworkConfiguration, + Args: cobra.ExactArgs(1), } privateNetworkConfigEditCmd.Flags().StringVar(&cloud.KubeSpec.PrivateNetworkConfiguration.DefaultVrackGateway, "default-vrack-gateway", "", "If defined, all egress traffic will be routed towards this IP address, which should belong to the private network") privateNetworkConfigEditCmd.Flags().BoolVar(&cloud.KubeSpec.PrivateNetworkConfiguration.PrivateNetworkRoutingAsDefault, "routing-as-default", false, "Set private network routing as default") @@ -260,29 +281,32 @@ func initKubeCommand(cloudCmd *cobra.Command) { kubeCmd.AddCommand(getKubeResetCmd()) kubeRestartCmd := &cobra.Command{ - Use: "restart ", - Short: "Restart control plane apiserver to invalidate cache without downtime", - Run: cloud.RestartKubeCluster, - Args: cobra.ExactArgs(1), + Use: "restart ", + Short: "Restart control plane apiserver to invalidate cache without downtime", + ValidArgsFunction: completion.CloudResources("/v1/cloud/project/%s/kube"), + Run: cloud.RestartKubeCluster, + Args: cobra.ExactArgs(1), } kubeRestartCmd.Flags().BoolVar(&cloud.KubeForceAction, "force", false, "Force restart the Kubernetes cluster (will create a slight downtime)") kubeCmd.AddCommand(kubeRestartCmd) kubeUpdateCmd := &cobra.Command{ - Use: "update ", - Short: "Update the given Kubernetes cluster", - Run: cloud.UpdateKubeCluster, - Args: cobra.ExactArgs(1), + Use: "update ", + Short: "Update the given Kubernetes cluster", + ValidArgsFunction: completion.CloudResources("/v1/cloud/project/%s/kube"), + Run: cloud.UpdateKubeCluster, + Args: cobra.ExactArgs(1), } kubeUpdateCmd.Flags().StringVar(&cloud.KubeUpdateStrategy, "strategy", "", "Update strategy to apply on your service (LATEST_PATCH, NEXT_MINOR)") kubeUpdateCmd.Flags().BoolVar(&cloud.KubeForceAction, "force", false, "Force redeploying the control plane / reinstalling the nodes regardless of their current version") kubeCmd.AddCommand(kubeUpdateCmd) kubeCmd.AddCommand(&cobra.Command{ - Use: "set-load-balancers-subnet ", - Short: "Update the load balancers subnet ID for the given Kubernetes cluster", - Run: cloud.UpdateKubeLoadBalancersSubnet, - Args: cobra.ExactArgs(2), + Use: "set-load-balancers-subnet ", + Short: "Update the load balancers subnet ID for the given Kubernetes cluster", + ValidArgsFunction: completion.CloudResources("/v1/cloud/project/%s/kube"), + Run: cloud.UpdateKubeLoadBalancersSubnet, + Args: cobra.ExactArgs(2), }) cloudCmd.AddCommand(kubeCmd) @@ -414,8 +438,9 @@ There are three ways to define the reset parameters: ovhcloud cloud managed-kubernetes reset --editor --version 1.31 `, - Run: cloud.ResetKubeCluster, - Args: cobra.ExactArgs(1), + ValidArgsFunction: completion.CloudResources("/v1/cloud/project/%s/kube"), + Run: cloud.ResetKubeCluster, + Args: cobra.ExactArgs(1), } // All flags for Kubernetes cluster reset @@ -458,10 +483,11 @@ There are three ways to define the reset parameters: func getNodepoolEditCmd() *cobra.Command { nodepoolEditCmd := &cobra.Command{ - Use: "edit ", - Short: "Edit the given Kubernetes node pool", - Run: cloud.EditKubeNodepool, - Args: cobra.ExactArgs(2), + Use: "edit ", + Short: "Edit the given Kubernetes node pool", + ValidArgsFunction: completion.CloudResources("/v1/cloud/project/%s/kube"), + Run: cloud.EditKubeNodepool, + Args: cobra.ExactArgs(2), } nodepoolEditCmd.Flags().BoolVar(&cloud.KubeNodepoolSpec.Autoscale, "autoscale", false, "Enable autoscaling for the node pool") nodepoolEditCmd.Flags().IntVar(&cloud.KubeNodepoolSpec.Autoscaling.ScaleDownUnneededTimeSeconds, "scale-down-unneeded-time-seconds", 0, "How long a node should be unneeded before it is eligible for scale down (seconds)") @@ -535,8 +561,9 @@ There are three ways to define the creation parameters: ovhcloud cloud managed-kubernetes nodepool create --editor --flavor-selector `, - Run: cloud.CreateKubeNodepool, - Args: cobra.ExactArgs(1), + ValidArgsFunction: completion.CloudResources("/v1/cloud/project/%s/kube"), + Run: cloud.CreateKubeNodepool, + Args: cobra.ExactArgs(1), } // All flags for node pool creation @@ -615,8 +642,9 @@ There are three ways to define the parameters: ovhcloud cloud managed-kubernetes oidc create --editor --client-id `, - Run: cloud.CreateKubeOIDCIntegration, - Args: cobra.ExactArgs(1), + ValidArgsFunction: completion.CloudResources("/v1/cloud/project/%s/kube"), + Run: cloud.CreateKubeOIDCIntegration, + Args: cobra.ExactArgs(1), } // All flags for OIDC integration creation diff --git a/internal/cmd/cloud_managed_rancher.go b/internal/cmd/cloud_managed_rancher.go index 6e78f353..b92e9caf 100644 --- a/internal/cmd/cloud_managed_rancher.go +++ b/internal/cmd/cloud_managed_rancher.go @@ -6,6 +6,7 @@ package cmd import ( "github.com/ovh/ovhcloud-cli/internal/assets" + "github.com/ovh/ovhcloud-cli/internal/completion" "github.com/ovh/ovhcloud-cli/internal/services/cloud" "github.com/spf13/cobra" ) @@ -27,10 +28,11 @@ func initCloudRancherCommand(cloudCmd *cobra.Command) { rancherCmd.AddCommand(withFilterFlag(rancherListCmd)) rancherCmd.AddCommand(&cobra.Command{ - Use: "get ", - Short: "Get a specific Rancher service", - Run: cloud.GetRancher, - Args: cobra.ExactArgs(1), + Use: "get ", + Short: "Get a specific Rancher service", + ValidArgsFunction: completion.CloudResources("/v2/publicCloud/project/%s/rancher"), + Run: cloud.GetRancher, + Args: cobra.ExactArgs(1), }) rancherCmd.AddCommand(getRancherEditCmd()) @@ -38,17 +40,19 @@ func initCloudRancherCommand(cloudCmd *cobra.Command) { rancherCmd.AddCommand(getRancherCreateCmd()) rancherCmd.AddCommand(&cobra.Command{ - Use: "reset-admin-credentials ", - Short: "Reset admin user credentials", - Run: cloud.ResetRancherAdminCredentials, - Args: cobra.ExactArgs(1), + Use: "reset-admin-credentials ", + Short: "Reset admin user credentials", + ValidArgsFunction: completion.CloudResources("/v2/publicCloud/project/%s/rancher"), + Run: cloud.ResetRancherAdminCredentials, + Args: cobra.ExactArgs(1), }) rancherCmd.AddCommand(&cobra.Command{ - Use: "delete ", - Short: "Delete a specific Rancher service", - Run: cloud.DeleteRancher, - Args: cobra.ExactArgs(1), + Use: "delete ", + Short: "Delete a specific Rancher service", + ValidArgsFunction: completion.CloudResources("/v2/publicCloud/project/%s/rancher"), + Run: cloud.DeleteRancher, + Args: cobra.ExactArgs(1), }) cloudCmd.AddCommand(rancherCmd) @@ -56,10 +60,11 @@ func initCloudRancherCommand(cloudCmd *cobra.Command) { func getRancherEditCmd() *cobra.Command { editRancherCmd := &cobra.Command{ - Use: "edit ", - Short: "Edit the given Rancher service", - Run: cloud.EditRancher, - Args: cobra.ExactArgs(1), + Use: "edit ", + Short: "Edit the given Rancher service", + ValidArgsFunction: completion.CloudResources("/v2/publicCloud/project/%s/rancher"), + Run: cloud.EditRancher, + Args: cobra.ExactArgs(1), } editRancherCmd.Flags().StringVar(&cloud.RancherSpec.TargetSpec.Name, "name", "", "Name of the managed Rancher service") diff --git a/internal/cmd/cloud_managed_registry.go b/internal/cmd/cloud_managed_registry.go index bd5b6fe2..5d9e1cf6 100644 --- a/internal/cmd/cloud_managed_registry.go +++ b/internal/cmd/cloud_managed_registry.go @@ -6,6 +6,7 @@ package cmd import ( "github.com/ovh/ovhcloud-cli/internal/assets" + "github.com/ovh/ovhcloud-cli/internal/completion" "github.com/ovh/ovhcloud-cli/internal/services/cloud" "github.com/spf13/cobra" ) @@ -27,17 +28,19 @@ func initContainerRegistryCommand(cloudCmd *cobra.Command) { registryCmd.AddCommand(withFilterFlag(listCmd)) registryCmd.AddCommand(&cobra.Command{ - Use: "get ", - Short: "Get a specific container registry", - Run: cloud.GetContainerRegistry, - Args: cobra.ExactArgs(1), + Use: "get ", + Short: "Get a specific container registry", + ValidArgsFunction: completion.CloudResources("/v1/cloud/project/%s/containerRegistry"), + Run: cloud.GetContainerRegistry, + Args: cobra.ExactArgs(1), }) editCmd := &cobra.Command{ - Use: "edit ", - Short: "Edit the given container registry", - Args: cobra.ExactArgs(1), - Run: cloud.EditContainerRegistry, + Use: "edit ", + Short: "Edit the given container registry", + Args: cobra.ExactArgs(1), + ValidArgsFunction: completion.CloudResources("/v1/cloud/project/%s/containerRegistry"), + Run: cloud.EditContainerRegistry, } editCmd.Flags().StringVar(&cloud.CloudContainerRegistryName, "name", "", "New name for the container registry") addInteractiveEditorFlag(editCmd) @@ -57,10 +60,11 @@ func initContainerRegistryCommand(cloudCmd *cobra.Command) { registryCmd.AddCommand(createCmd) registryCmd.AddCommand(&cobra.Command{ - Use: "delete ", - Short: "Delete a specific container registry", - Run: cloud.DeleteContainerRegistry, - Args: cobra.ExactArgs(1), + Use: "delete ", + Short: "Delete a specific container registry", + ValidArgsFunction: completion.CloudResources("/v1/cloud/project/%s/containerRegistry"), + Run: cloud.DeleteContainerRegistry, + Args: cobra.ExactArgs(1), }) initContainerRegistryUsersCommand(registryCmd) @@ -79,25 +83,28 @@ func initContainerRegistryUsersCommand(registryCmd *cobra.Command) { } listCmd := &cobra.Command{ - Use: "list ", - Aliases: []string{"ls"}, - Short: "List your container registry users", - Run: cloud.ListContainerRegistryUsers, + Use: "list ", + Aliases: []string{"ls"}, + Short: "List your container registry users", + ValidArgsFunction: completion.CloudResources("/v1/cloud/project/%s/containerRegistry"), + Run: cloud.ListContainerRegistryUsers, } usersCmd.AddCommand(withFilterFlag(listCmd)) usersCmd.AddCommand(&cobra.Command{ - Use: "get ", - Short: "Get a specific container registry user", - Run: cloud.GetContainerRegistryUser, - Args: cobra.ExactArgs(2), + Use: "get ", + Short: "Get a specific container registry user", + ValidArgsFunction: completion.CloudResourceWithChild("/v1/cloud/project/%s/containerRegistry", "/v1/cloud/project/%s/containerRegistry/%s/users"), + Run: cloud.GetContainerRegistryUser, + Args: cobra.ExactArgs(2), }) createCmd := &cobra.Command{ - Use: "create ", - Short: "Create a new container registry user", - Args: cobra.ExactArgs(1), - Run: cloud.CreateContainerRegistryUser, + Use: "create ", + Short: "Create a new container registry user", + Args: cobra.ExactArgs(1), + ValidArgsFunction: completion.CloudResources("/v1/cloud/project/%s/containerRegistry"), + Run: cloud.CreateContainerRegistryUser, } createCmd.Flags().StringVar(&cloud.CloudContainerRegistryUserSpec.Email, "email", "", "User email") createCmd.Flags().StringVar(&cloud.CloudContainerRegistryUserSpec.Login, "login", "", "User login") @@ -107,17 +114,19 @@ func initContainerRegistryUsersCommand(registryCmd *cobra.Command) { usersCmd.AddCommand(createCmd) usersCmd.AddCommand(&cobra.Command{ - Use: "set-as-admin ", - Short: "Set a specific container registry user as admin", - Run: cloud.SetContainerRegistryUserAsAdmin, - Args: cobra.ExactArgs(2), + Use: "set-as-admin ", + Short: "Set a specific container registry user as admin", + ValidArgsFunction: completion.CloudResources("/v1/cloud/project/%s/containerRegistry"), + Run: cloud.SetContainerRegistryUserAsAdmin, + Args: cobra.ExactArgs(2), }) usersCmd.AddCommand(&cobra.Command{ - Use: "delete ", - Short: "Delete a specific container registry user", - Run: cloud.DeleteContainerRegistryUser, - Args: cobra.ExactArgs(2), + Use: "delete ", + Short: "Delete a specific container registry user", + ValidArgsFunction: completion.CloudResourceWithChild("/v1/cloud/project/%s/containerRegistry", "/v1/cloud/project/%s/containerRegistry/%s/users"), + Run: cloud.DeleteContainerRegistryUser, + Args: cobra.ExactArgs(2), }) registryCmd.AddCommand(usersCmd) @@ -130,10 +139,11 @@ func initContainerRegistryIAMCommand(registryCmd *cobra.Command) { } enableCmd := &cobra.Command{ - Use: "enable ", - Short: "Enable IAM for the given container registry", - Args: cobra.ExactArgs(1), - Run: cloud.EnableContainerRegistryIAM, + Use: "enable ", + Short: "Enable IAM for the given container registry", + Args: cobra.ExactArgs(1), + ValidArgsFunction: completion.CloudResources("/v1/cloud/project/%s/containerRegistry"), + Run: cloud.EnableContainerRegistryIAM, } enableCmd.Flags().BoolVar(&cloud.CloudContainerRegistryIamSpec.DeleteUsers, "delete-users", false, "Delete existing container registry users when enabling IAM") addParameterFileFlags(enableCmd, false, assets.CloudOpenapiSchema, "/cloud/project/{serviceName}/containerRegistry/{registryId}/iam", "post", cloud.CloudContainerRegistryIamEnableSample, nil) @@ -142,10 +152,11 @@ func initContainerRegistryIAMCommand(registryCmd *cobra.Command) { iamCmd.AddCommand(enableCmd) iamCmd.AddCommand(&cobra.Command{ - Use: "disable ", - Short: "Disable IAM for the given container registry", - Args: cobra.ExactArgs(1), - Run: cloud.DisableContainerRegistryIAM, + Use: "disable ", + Short: "Disable IAM for the given container registry", + Args: cobra.ExactArgs(1), + ValidArgsFunction: completion.CloudResources("/v1/cloud/project/%s/containerRegistry"), + Run: cloud.DisableContainerRegistryIAM, }) registryCmd.AddCommand(iamCmd) @@ -171,19 +182,21 @@ func initContainerRegistryIPRestrictionsManagementCommand(ipRestrictionsCmd *cob } listCmd := &cobra.Command{ - Use: "list ", - Aliases: []string{"ls"}, - Short: "List management IP restrictions for a container registry", - Run: cloud.ListContainerRegistryIPRestrictionsManagement, - Args: cobra.ExactArgs(1), + Use: "list ", + Aliases: []string{"ls"}, + Short: "List management IP restrictions for a container registry", + ValidArgsFunction: completion.CloudResources("/v1/cloud/project/%s/containerRegistry"), + Run: cloud.ListContainerRegistryIPRestrictionsManagement, + Args: cobra.ExactArgs(1), } managementCmd.AddCommand(withFilterFlag(listCmd)) addCmd := &cobra.Command{ - Use: "add ", - Short: "Add a management IP restriction to a container registry", - Run: cloud.AddContainerRegistryIPRestrictionsManagement, - Args: cobra.ExactArgs(1), + Use: "add ", + Short: "Add a management IP restriction to a container registry", + ValidArgsFunction: completion.CloudResources("/v1/cloud/project/%s/containerRegistry"), + Run: cloud.AddContainerRegistryIPRestrictionsManagement, + Args: cobra.ExactArgs(1), } addCmd.Flags().StringVar(&cloud.ContainerRegistryIPRestrictionsAddSpec.IPBlock, "ip-block", "", "IP block in CIDR notation (e.g., 192.0.2.0/24)") addCmd.MarkFlagRequired("ip-block") //nolint:errcheck @@ -191,10 +204,11 @@ func initContainerRegistryIPRestrictionsManagementCommand(ipRestrictionsCmd *cob managementCmd.AddCommand(addCmd) deleteCmd := &cobra.Command{ - Use: "delete ", - Short: "Delete a management IP restriction from a container registry", - Run: cloud.DeleteContainerRegistryIPRestrictionsManagement, - Args: cobra.ExactArgs(1), + Use: "delete ", + Short: "Delete a management IP restriction from a container registry", + ValidArgsFunction: completion.CloudResources("/v1/cloud/project/%s/containerRegistry"), + Run: cloud.DeleteContainerRegistryIPRestrictionsManagement, + Args: cobra.ExactArgs(1), } deleteCmd.Flags().StringVar(&cloud.ContainerRegistryIPRestrictionsDeleteSpec.IPBlock, "ip-block", "", "IP block in CIDR notation to delete (e.g., 192.0.2.0/24)") deleteCmd.MarkFlagRequired("ip-block") //nolint:errcheck @@ -211,19 +225,21 @@ func initContainerRegistryIPRestrictionsRegistryCommand(ipRestrictionsCmd *cobra } listCmd := &cobra.Command{ - Use: "list ", - Aliases: []string{"ls"}, - Short: "List registry IP restrictions for a container registry", - Run: cloud.ListContainerRegistryIPRestrictionsRegistry, - Args: cobra.ExactArgs(1), + Use: "list ", + Aliases: []string{"ls"}, + Short: "List registry IP restrictions for a container registry", + ValidArgsFunction: completion.CloudResources("/v1/cloud/project/%s/containerRegistry"), + Run: cloud.ListContainerRegistryIPRestrictionsRegistry, + Args: cobra.ExactArgs(1), } registryRestrictionsCmd.AddCommand(withFilterFlag(listCmd)) addCmd := &cobra.Command{ - Use: "add ", - Short: "Add a registry IP restriction to a container registry", - Run: cloud.AddContainerRegistryIPRestrictionsRegistry, - Args: cobra.ExactArgs(1), + Use: "add ", + Short: "Add a registry IP restriction to a container registry", + ValidArgsFunction: completion.CloudResources("/v1/cloud/project/%s/containerRegistry"), + Run: cloud.AddContainerRegistryIPRestrictionsRegistry, + Args: cobra.ExactArgs(1), } addCmd.Flags().StringVar(&cloud.ContainerRegistryIPRestrictionsAddSpec.IPBlock, "ip-block", "", "IP block in CIDR notation (e.g., 192.0.2.0/24)") addCmd.MarkFlagRequired("ip-block") //nolint:errcheck @@ -231,10 +247,11 @@ func initContainerRegistryIPRestrictionsRegistryCommand(ipRestrictionsCmd *cobra registryRestrictionsCmd.AddCommand(addCmd) deleteCmd := &cobra.Command{ - Use: "delete ", - Short: "Delete a registry IP restriction from a container registry", - Run: cloud.DeleteContainerRegistryIPRestrictionsRegistry, - Args: cobra.ExactArgs(1), + Use: "delete ", + Short: "Delete a registry IP restriction from a container registry", + ValidArgsFunction: completion.CloudResources("/v1/cloud/project/%s/containerRegistry"), + Run: cloud.DeleteContainerRegistryIPRestrictionsRegistry, + Args: cobra.ExactArgs(1), } deleteCmd.Flags().StringVar(&cloud.ContainerRegistryIPRestrictionsDeleteSpec.IPBlock, "ip-block", "", "IP block in CIDR notation to delete (e.g., 192.0.2.0/24)") deleteCmd.MarkFlagRequired("ip-block") //nolint:errcheck @@ -250,18 +267,20 @@ func initContainerRegistryOIDCCommand(registryCmd *cobra.Command) { } getCmd := &cobra.Command{ - Use: "get ", - Short: "Get OIDC configuration for a container registry", - Args: cobra.ExactArgs(1), - Run: cloud.GetContainerRegistryOIDC, + Use: "get ", + Short: "Get OIDC configuration for a container registry", + Args: cobra.ExactArgs(1), + ValidArgsFunction: completion.CloudResources("/v1/cloud/project/%s/containerRegistry"), + Run: cloud.GetContainerRegistryOIDC, } oidcCmd.AddCommand(getCmd) createCmd := &cobra.Command{ - Use: "create ", - Short: "Create a new OIDC configuration for a container registry", - Args: cobra.ExactArgs(1), - Run: cloud.CreateContainerRegistryOIDC, + Use: "create ", + Short: "Create a new OIDC configuration for a container registry", + Args: cobra.ExactArgs(1), + ValidArgsFunction: completion.CloudResources("/v1/cloud/project/%s/containerRegistry"), + Run: cloud.CreateContainerRegistryOIDC, } createCmd.Flags().BoolVar(&cloud.CloudContainerRegistryOidcCreateSpec.DeleteUsers, "delete-users", false, "Delete existing local users when enabling OIDC") createCmd.Flags().StringVar(&cloud.CloudContainerRegistryOidcCreateSpec.Provider.Name, "name", "", "OIDC provider name") @@ -281,10 +300,11 @@ func initContainerRegistryOIDCCommand(registryCmd *cobra.Command) { oidcCmd.AddCommand(createCmd) editCmd := &cobra.Command{ - Use: "edit ", - Short: "Edit the OIDC configuration for a container registry", - Args: cobra.ExactArgs(1), - Run: cloud.EditContainerRegistryOIDC, + Use: "edit ", + Short: "Edit the OIDC configuration for a container registry", + Args: cobra.ExactArgs(1), + ValidArgsFunction: completion.CloudResources("/v1/cloud/project/%s/containerRegistry"), + Run: cloud.EditContainerRegistryOIDC, } editCmd.Flags().StringVar(&cloud.CloudContainerRegistryOidcEditSpec.AdminGroup, "admin-group", "", "Group granted admin role") editCmd.Flags().StringVar(&cloud.CloudContainerRegistryOidcEditSpec.ClientID, "client-id", "", "OIDC client ID") @@ -301,10 +321,11 @@ func initContainerRegistryOIDCCommand(registryCmd *cobra.Command) { oidcCmd.AddCommand(editCmd) deleteCmd := &cobra.Command{ - Use: "delete ", - Short: "Delete the OIDC configuration for a container registry", - Args: cobra.ExactArgs(1), - Run: cloud.DeleteContainerRegistryOIDC, + Use: "delete ", + Short: "Delete the OIDC configuration for a container registry", + Args: cobra.ExactArgs(1), + ValidArgsFunction: completion.CloudResources("/v1/cloud/project/%s/containerRegistry"), + Run: cloud.DeleteContainerRegistryOIDC, } oidcCmd.AddCommand(deleteCmd) @@ -318,18 +339,20 @@ func initContainerRegistryPlanCommand(registryCmd *cobra.Command) { } listCapabilitiesCmd := &cobra.Command{ - Use: "list-capabilities ", - Short: "List available plans for a specific container registry", - Args: cobra.ExactArgs(1), - Run: cloud.ListContainerRegistryPlanCapabilities, + Use: "list-capabilities ", + Short: "List available plans for a specific container registry", + Args: cobra.ExactArgs(1), + ValidArgsFunction: completion.CloudResources("/v1/cloud/project/%s/containerRegistry"), + Run: cloud.ListContainerRegistryPlanCapabilities, } planCmd.AddCommand(withFilterFlag(listCapabilitiesCmd)) upgradeCmd := &cobra.Command{ - Use: "upgrade ", - Short: "Upgrade a container registry plan", - Args: cobra.ExactArgs(1), - Run: cloud.UpgradeContainerRegistryPlan, + Use: "upgrade ", + Short: "Upgrade a container registry plan", + Args: cobra.ExactArgs(1), + ValidArgsFunction: completion.CloudResources("/v1/cloud/project/%s/containerRegistry"), + Run: cloud.UpgradeContainerRegistryPlan, } upgradeCmd.Flags().StringVar(&cloud.CloudContainerRegistryPlanUpgradeSpec.PlanID, "plan-id", "", "Target plan ID for the registry") upgradeCmd.MarkFlagRequired("plan-id") //nolint:errcheck diff --git a/internal/cmd/cloud_operation.go b/internal/cmd/cloud_operation.go index e14430a4..ce3ca4a8 100644 --- a/internal/cmd/cloud_operation.go +++ b/internal/cmd/cloud_operation.go @@ -5,6 +5,7 @@ package cmd import ( + "github.com/ovh/ovhcloud-cli/internal/completion" "github.com/ovh/ovhcloud-cli/internal/services/cloud" "github.com/spf13/cobra" ) @@ -25,10 +26,11 @@ func initCloudOperationCommand(cloudCmd *cobra.Command) { operationCmd.AddCommand(withFilterFlag(operationListCmd)) operationCmd.AddCommand(&cobra.Command{ - Use: "get ", - Short: "Get a specific operation", - Run: cloud.GetCloudOperation, - Args: cobra.ExactArgs(1), + Use: "get ", + Short: "Get a specific operation", + ValidArgsFunction: completion.CloudResources("/v1/cloud/project/%s/operation"), + Run: cloud.GetCloudOperation, + Args: cobra.ExactArgs(1), }) cloudCmd.AddCommand(operationCmd) diff --git a/internal/cmd/cloud_project.go b/internal/cmd/cloud_project.go index 86f5658e..d611646f 100644 --- a/internal/cmd/cloud_project.go +++ b/internal/cmd/cloud_project.go @@ -5,6 +5,7 @@ package cmd import ( + "github.com/ovh/ovhcloud-cli/internal/completion" "github.com/ovh/ovhcloud-cli/internal/services/cloud" "github.com/spf13/cobra" ) @@ -31,17 +32,19 @@ func init() { // Command to get a single CloudProject cloudprojectCmd.AddCommand(&cobra.Command{ - Use: "get ", - Short: "Retrieve information of a specific cloud project", - Args: cobra.ExactArgs(1), - Run: cloud.GetCloudProject, + Use: "get ", + Short: "Retrieve information of a specific cloud project", + Args: cobra.ExactArgs(1), + ValidArgsFunction: completion.ServiceList("/v1/cloud/project"), + Run: cloud.GetCloudProject, }) editCloudProjectCmd := &cobra.Command{ - Use: "edit ", - Short: "Edit the given cloud project", - Args: cobra.ExactArgs(1), - Run: cloud.EditCloudProject, + Use: "edit ", + Short: "Edit the given cloud project", + Args: cobra.ExactArgs(1), + ValidArgsFunction: completion.ServiceList("/v1/cloud/project"), + Run: cloud.EditCloudProject, } editCloudProjectCmd.Flags().StringVar(&cloud.CloudProjectSpec.Description, "description", "", "Description of the project") editCloudProjectCmd.Flags().BoolVar(&cloud.CloudProjectSpec.ManualQuota, "manual-quota", false, "Prevent automatic quota upgrade") @@ -121,5 +124,21 @@ func init() { initCloudAlertingCommand(cloudCmd) cloudCmd.AddCommand(cloudprojectCmd) + + // Register the cloud-project flag completion on every (sub)command exposing it, + // instead of repeating the registration in each command definition. + registerCloudProjectCompletion(cloudCmd) + rootCmd.AddCommand(cloudCmd) } + +// registerCloudProjectCompletion walks the command tree and registers the +// completion function for the "cloud-project" flag on every command that exposes it. +func registerCloudProjectCompletion(cmd *cobra.Command) { + if cmd.PersistentFlags().Lookup("cloud-project") != nil { + cmd.RegisterFlagCompletionFunc("cloud-project", completion.CloudProjects) //nolint:errcheck + } + for _, child := range cmd.Commands() { + registerCloudProjectCompletion(child) + } +} diff --git a/internal/cmd/cloud_region.go b/internal/cmd/cloud_region.go index 69ca4228..d9432623 100644 --- a/internal/cmd/cloud_region.go +++ b/internal/cmd/cloud_region.go @@ -5,6 +5,7 @@ package cmd import ( + "github.com/ovh/ovhcloud-cli/internal/completion" "github.com/ovh/ovhcloud-cli/internal/services/cloud" "github.com/spf13/cobra" ) @@ -25,10 +26,11 @@ func initCloudRegionCommand(cloudCmd *cobra.Command) { regionCmd.AddCommand(withFilterFlag(regionListCmd)) regionCmd.AddCommand(&cobra.Command{ - Use: "get ", - Short: "Get information about a region", - Run: cloud.GetCloudRegion, - Args: cobra.ExactArgs(1), + Use: "get ", + Short: "Get information about a region", + ValidArgsFunction: completion.CloudResources("/v1/cloud/project/%s/region"), + Run: cloud.GetCloudRegion, + Args: cobra.ExactArgs(1), }) cloudCmd.AddCommand(regionCmd) diff --git a/internal/cmd/cloud_ssh_key.go b/internal/cmd/cloud_ssh_key.go index 2778040a..16650153 100644 --- a/internal/cmd/cloud_ssh_key.go +++ b/internal/cmd/cloud_ssh_key.go @@ -6,6 +6,7 @@ package cmd import ( "github.com/ovh/ovhcloud-cli/internal/assets" + "github.com/ovh/ovhcloud-cli/internal/completion" "github.com/ovh/ovhcloud-cli/internal/services/cloud" "github.com/spf13/cobra" ) @@ -26,10 +27,11 @@ func initCloudSSHKeyCommand(cloudCmd *cobra.Command) { sshKeyCmd.AddCommand(withFilterFlag(sshKeyListCmd)) sshKeyCmd.AddCommand(&cobra.Command{ - Use: "get ", - Short: "Get information about a SSH key", - Run: cloud.GetCloudSSHKey, - Args: cobra.ExactArgs(1), + Use: "get ", + Short: "Get information about a SSH key", + ValidArgsFunction: completion.CloudResources("/v1/cloud/project/%s/sshkey"), + Run: cloud.GetCloudSSHKey, + Args: cobra.ExactArgs(1), }) sshKeyCreateCmd := &cobra.Command{ @@ -46,10 +48,11 @@ func initCloudSSHKeyCommand(cloudCmd *cobra.Command) { sshKeyCmd.AddCommand(sshKeyCreateCmd) sshKeyCmd.AddCommand(&cobra.Command{ - Use: "delete ", - Short: "Delete a SSH key", - Run: cloud.DeleteCloudSSHKey, - Args: cobra.ExactArgs(1), + Use: "delete ", + Short: "Delete a SSH key", + ValidArgsFunction: completion.CloudResources("/v1/cloud/project/%s/sshkey"), + Run: cloud.DeleteCloudSSHKey, + Args: cobra.ExactArgs(1), }) cloudCmd.AddCommand(sshKeyCmd) diff --git a/internal/cmd/cloud_storage_block.go b/internal/cmd/cloud_storage_block.go index 3308d7d7..d14387f2 100644 --- a/internal/cmd/cloud_storage_block.go +++ b/internal/cmd/cloud_storage_block.go @@ -6,6 +6,7 @@ package cmd import ( "github.com/ovh/ovhcloud-cli/internal/assets" + "github.com/ovh/ovhcloud-cli/internal/completion" "github.com/ovh/ovhcloud-cli/internal/flags" "github.com/ovh/ovhcloud-cli/internal/services/cloud" "github.com/spf13/cobra" @@ -27,17 +28,19 @@ func initCloudVolumeCommand(cloudCmd *cobra.Command) { storageBlockCmd.AddCommand(withFilterFlag(volumeListCmd)) storageBlockCmd.AddCommand(&cobra.Command{ - Use: "get ", - Short: "Get a specific volume", - Run: cloud.GetVolume, - Args: cobra.ExactArgs(1), + Use: "get ", + Short: "Get a specific volume", + ValidArgsFunction: completion.CloudResources("/v1/cloud/project/%s/volume"), + Run: cloud.GetVolume, + Args: cobra.ExactArgs(1), }) volumeEditCmd := &cobra.Command{ - Use: "edit ", - Short: "Edit the given volume", - Run: cloud.EditVolume, - Args: cobra.ExactArgs(1), + Use: "edit ", + Short: "Edit the given volume", + ValidArgsFunction: completion.CloudResources("/v1/cloud/project/%s/volume"), + Run: cloud.EditVolume, + Args: cobra.ExactArgs(1), } volumeEditCmd.Flags().StringVar(&cloud.VolumeEditSpec.Description, "description", "", "Volume description") volumeEditCmd.Flags().StringVar(&cloud.VolumeEditSpec.Name, "name", "", "Volume name") @@ -49,25 +52,28 @@ func initCloudVolumeCommand(cloudCmd *cobra.Command) { storageBlockCmd.AddCommand(getVolumeCreateCmd()) storageBlockCmd.AddCommand(&cobra.Command{ - Use: "delete ", - Short: "Delete the given volume", - Run: cloud.DeleteVolume, - Args: cobra.ExactArgs(1), + Use: "delete ", + Short: "Delete the given volume", + ValidArgsFunction: completion.CloudResources("/v1/cloud/project/%s/volume"), + Run: cloud.DeleteVolume, + Args: cobra.ExactArgs(1), }) // Volume action commands storageBlockCmd.AddCommand(&cobra.Command{ - Use: "attach ", - Short: "Attach the given volume to the given instance", - Run: cloud.AttachVolumeToInstance, - Args: cobra.ExactArgs(2), + Use: "attach ", + Short: "Attach the given volume to the given instance", + ValidArgsFunction: completion.CloudResources("/v1/cloud/project/%s/volume"), + Run: cloud.AttachVolumeToInstance, + Args: cobra.ExactArgs(2), }) storageBlockCmd.AddCommand(&cobra.Command{ - Use: "detach ", - Short: "Detach the given volume from the given instance", - Run: cloud.DetachVolumeFromInstance, - Args: cobra.ExactArgs(2), + Use: "detach ", + Short: "Detach the given volume from the given instance", + ValidArgsFunction: completion.CloudResources("/v1/cloud/project/%s/volume"), + Run: cloud.DetachVolumeFromInstance, + Args: cobra.ExactArgs(2), }) // Volume snapshot commands @@ -78,10 +84,11 @@ func initCloudVolumeCommand(cloudCmd *cobra.Command) { storageBlockCmd.AddCommand(volumeSnapshotCmd) volumeSnapshotCreateCmd := &cobra.Command{ - Use: "create ", - Short: "Create a snapshot of the given volume", - Run: cloud.CreateVolumeSnapshot, - Args: cobra.ExactArgs(1), + Use: "create ", + Short: "Create a snapshot of the given volume", + ValidArgsFunction: completion.CloudResources("/v1/cloud/project/%s/volume"), + Run: cloud.CreateVolumeSnapshot, + Args: cobra.ExactArgs(1), } volumeSnapshotCreateCmd.Flags().StringVar(&cloud.VolumeSnapShotSpec.Description, "description", "", "Snapshot description") volumeSnapshotCreateCmd.Flags().StringVar(&cloud.VolumeSnapShotSpec.Name, "name", "", "Snapshot name") @@ -126,10 +133,11 @@ func initCloudVolumeCommand(cloudCmd *cobra.Command) { }) volumeBackupCmd.AddCommand(&cobra.Command{ - Use: "create ", - Short: "Create a backup of the given volume", - Run: cloud.CreateVolumeBackup, - Args: cobra.ExactArgs(2), + Use: "create ", + Short: "Create a backup of the given volume", + ValidArgsFunction: completion.CloudResources("/v1/cloud/project/%s/volume"), + Run: cloud.CreateVolumeBackup, + Args: cobra.ExactArgs(2), }) volumeBackupCmd.AddCommand(&cobra.Command{ diff --git a/internal/cmd/cloud_storage_swift.go b/internal/cmd/cloud_storage_swift.go index ec1a0445..d10f9110 100644 --- a/internal/cmd/cloud_storage_swift.go +++ b/internal/cmd/cloud_storage_swift.go @@ -5,6 +5,7 @@ package cmd import ( + "github.com/ovh/ovhcloud-cli/internal/completion" "github.com/ovh/ovhcloud-cli/internal/services/cloud" "github.com/spf13/cobra" ) @@ -25,17 +26,19 @@ func initCloudStorageSwiftCommand(cloudCmd *cobra.Command) { storageSwiftCmd.AddCommand(withFilterFlag(storageSwiftListCmd)) storageSwiftCmd.AddCommand(&cobra.Command{ - Use: "get ", - Short: "Get a specific SWIFT storage container", - Run: cloud.GetStorageSwift, - Args: cobra.ExactArgs(1), + Use: "get ", + Short: "Get a specific SWIFT storage container", + ValidArgsFunction: completion.CloudResources("/v1/cloud/project/%s/storage"), + Run: cloud.GetStorageSwift, + Args: cobra.ExactArgs(1), }) editCmd := &cobra.Command{ - Use: "edit ", - Short: "Edit the given SWIFT storage container", - Args: cobra.ExactArgs(1), - Run: cloud.EditStorageSwift, + Use: "edit ", + Short: "Edit the given SWIFT storage container", + Args: cobra.ExactArgs(1), + ValidArgsFunction: completion.CloudResources("/v1/cloud/project/%s/storage"), + Run: cloud.EditStorageSwift, } editCmd.Flags().StringVar(&cloud.CloudSwiftContainerType, "type", "", "Type of the SWIFT storage container (private, public, static)") addInteractiveEditorFlag(editCmd) diff --git a/internal/cmd/cloud_user.go b/internal/cmd/cloud_user.go index d4618dfe..ced229ff 100644 --- a/internal/cmd/cloud_user.go +++ b/internal/cmd/cloud_user.go @@ -6,6 +6,7 @@ package cmd import ( "github.com/ovh/ovhcloud-cli/internal/assets" + "github.com/ovh/ovhcloud-cli/internal/completion" "github.com/ovh/ovhcloud-cli/internal/services/cloud" "github.com/spf13/cobra" ) @@ -26,10 +27,11 @@ func initCloudUserCommand(cloudCmd *cobra.Command) { userCmd.AddCommand(withFilterFlag(userListCmd)) userCmd.AddCommand(&cobra.Command{ - Use: "get ", - Short: "Get information about a user", - Run: cloud.GetCloudUser, - Args: cobra.ExactArgs(1), + Use: "get ", + Short: "Get information about a user", + ValidArgsFunction: completion.CloudResources("/v1/cloud/project/%s/user"), + Run: cloud.GetCloudUser, + Args: cobra.ExactArgs(1), }) userCreateCmd := &cobra.Command{ @@ -45,10 +47,11 @@ func initCloudUserCommand(cloudCmd *cobra.Command) { userCmd.AddCommand(userCreateCmd) userCmd.AddCommand(&cobra.Command{ - Use: "delete ", - Short: "Delete the given user", - Run: cloud.DeleteCloudUser, - Args: cobra.ExactArgs(1), + Use: "delete ", + Short: "Delete the given user", + ValidArgsFunction: completion.CloudResources("/v1/cloud/project/%s/user"), + Run: cloud.DeleteCloudUser, + Args: cobra.ExactArgs(1), }) // S3 policy commands @@ -59,17 +62,19 @@ func initCloudUserCommand(cloudCmd *cobra.Command) { userCmd.AddCommand(s3PolicyCmd) s3PolicyCmd.AddCommand(&cobra.Command{ - Use: "get ", - Short: "Get the policy for the given user ID", - Run: cloud.GetUserS3Policy, - Args: cobra.ExactArgs(1), + Use: "get ", + Short: "Get the policy for the given user ID", + ValidArgsFunction: completion.CloudResources("/v1/cloud/project/%s/user"), + Run: cloud.GetUserS3Policy, + Args: cobra.ExactArgs(1), }) s3PolicyCreateCmd := &cobra.Command{ - Use: "create ", - Short: "Create a policy for the given user ID", - Run: cloud.CreateUserS3Policy, - Args: cobra.ExactArgs(1), + Use: "create ", + Short: "Create a policy for the given user ID", + ValidArgsFunction: completion.CloudResources("/v1/cloud/project/%s/user"), + Run: cloud.CreateUserS3Policy, + Args: cobra.ExactArgs(1), } s3PolicyCreateCmd.Flags().StringVar(&cloud.StorageS3ContainerPolicySpec.Policy, "policy", "", "Policy in JSON format") addParameterFileFlags(s3PolicyCreateCmd, false, assets.CloudOpenapiSchema, "/cloud/project/{serviceName}/user/{userId}/policy", "post", cloud.CloudStorageS3ContainerPolicyExample, nil) diff --git a/internal/cmd/completion.go b/internal/cmd/completion.go new file mode 100644 index 00000000..61be777c --- /dev/null +++ b/internal/cmd/completion.go @@ -0,0 +1,133 @@ +// SPDX-FileCopyrightText: 2025 OVH SAS +// +// SPDX-License-Identifier: Apache-2.0 + +//go:build !(js && wasm) + +package cmd + +import ( + "fmt" + "os" + "path/filepath" + "strings" + + "github.com/spf13/cobra" +) + +func init() { + completionCmd := &cobra.Command{ + Use: "completion [bash|zsh|fish|powershell]", + Short: "Generate shell completion scripts", + Long: `Generate shell completion scripts for ovhcloud CLI. + +To load completions in your current shell session: + + bash: + source <(ovhcloud completion bash) + + zsh: + source <(ovhcloud completion zsh) + + fish: + ovhcloud completion fish | source + +To make completions permanent, run: + + ovhcloud completion install +`, + ValidArgs: []string{"bash", "zsh", "fish", "powershell"}, + Args: cobra.MatchAll(cobra.MaximumNArgs(1), cobra.OnlyValidArgs), + RunE: func(cmd *cobra.Command, args []string) error { + if len(args) == 0 { + return cmd.Help() + } + switch args[0] { + case "bash": + return rootCmd.GenBashCompletion(os.Stdout) + case "zsh": + return rootCmd.GenZshCompletion(os.Stdout) + case "fish": + return rootCmd.GenFishCompletion(os.Stdout, true) + case "powershell": + return rootCmd.GenPowerShellCompletionWithDesc(os.Stdout) + } + return nil + }, + } + + completionCmd.AddCommand(&cobra.Command{ + Use: "install", + Short: "Install shell completion permanently in your shell rc file", + RunE: runCompletionInstall, + }) + + rootCmd.AddCommand(completionCmd) +} + +func runCompletionInstall(_ *cobra.Command, _ []string) error { + shell := os.Getenv("SHELL") + if shell == "" { + return fmt.Errorf("SHELL environment variable is not set — please run 'ovhcloud completion bash|zsh|fish|powershell' manually") + } + shellName := filepath.Base(shell) + + var rcFile string + var completionLine string + home, err := os.UserHomeDir() + if err != nil { + return fmt.Errorf("failed to determine user home directory: %w", err) + } + + switch shellName { + case "bash": + rcFile = filepath.Join(home, ".bashrc") + completionLine = `eval "$(ovhcloud completion bash)"` + case "zsh": + rcFile = filepath.Join(home, ".zshrc") + completionLine = `eval "$(ovhcloud completion zsh)"` + case "fish": + configDir := os.Getenv("XDG_CONFIG_HOME") + if configDir == "" { + configDir = filepath.Join(home, ".config") + } + fishCompDir := filepath.Join(configDir, "fish", "completions") + if err := os.MkdirAll(fishCompDir, 0755); err != nil { + return fmt.Errorf("failed to create fish completions dir: %w", err) + } + destFile := filepath.Join(fishCompDir, "ovhcloud.fish") + f, err := os.Create(destFile) + if err != nil { + return fmt.Errorf("failed to create fish completion file: %w", err) + } + defer f.Close() + if err := rootCmd.GenFishCompletion(f, true); err != nil { + return fmt.Errorf("failed to write fish completion: %w", err) + } + fmt.Printf("✅ Fish completion installed to %s\n", destFile) + return nil + default: + return fmt.Errorf("unsupported shell %q — please run 'ovhcloud completion bash|zsh|fish|powershell' manually", shellName) + } + + // Check if already installed + content, err := os.ReadFile(rcFile) + if err == nil && strings.Contains(string(content), completionLine) { + fmt.Printf("✅ Completion already installed in %s\n", rcFile) + return nil + } + + f, err := os.OpenFile(rcFile, os.O_APPEND|os.O_WRONLY|os.O_CREATE, 0644) + if err != nil { + return fmt.Errorf("failed to open %s: %w", rcFile, err) + } + defer f.Close() + + if _, err := fmt.Fprintf(f, "\n# ovhcloud CLI shell completion\n%s\n", completionLine); err != nil { + return fmt.Errorf("failed to write to %s: %w", rcFile, err) + } + + fmt.Printf("✅ Completion installed in %s\n", rcFile) + fmt.Printf(" Reload your shell or run: source %s\n", rcFile) + return nil +} diff --git a/internal/cmd/completion_test.go b/internal/cmd/completion_test.go new file mode 100644 index 00000000..fe97f083 --- /dev/null +++ b/internal/cmd/completion_test.go @@ -0,0 +1,165 @@ +// SPDX-FileCopyrightText: 2025 OVH SAS +// +// SPDX-License-Identifier: Apache-2.0 + +//go:build !(js && wasm) + +package cmd + +import ( + "os" + "path/filepath" + "strings" + "testing" +) + +// setupHome isolates HOME (and clears XDG_CONFIG_HOME) so completion install +// writes into a throwaway directory instead of the real user home. +func setupHome(t *testing.T) string { + t.Helper() + home := t.TempDir() + t.Setenv("HOME", home) + t.Setenv("XDG_CONFIG_HOME", "") + return home +} + +func TestCompletionInstall_Bash(t *testing.T) { + home := setupHome(t) + t.Setenv("SHELL", "/usr/bin/bash") + + if err := runCompletionInstall(nil, nil); err != nil { + t.Fatalf("unexpected error: %v", err) + } + + content, err := os.ReadFile(filepath.Join(home, ".bashrc")) + if err != nil { + t.Fatalf(".bashrc was not created: %v", err) + } + if !strings.Contains(string(content), `eval "$(ovhcloud completion bash)"`) { + t.Errorf(".bashrc does not contain the bash completion line:\n%s", content) + } +} + +func TestCompletionInstall_Zsh(t *testing.T) { + home := setupHome(t) + t.Setenv("SHELL", "/bin/zsh") + + if err := runCompletionInstall(nil, nil); err != nil { + t.Fatalf("unexpected error: %v", err) + } + + content, err := os.ReadFile(filepath.Join(home, ".zshrc")) + if err != nil { + t.Fatalf(".zshrc was not created: %v", err) + } + if !strings.Contains(string(content), `eval "$(ovhcloud completion zsh)"`) { + t.Errorf(".zshrc does not contain the zsh completion line:\n%s", content) + } +} + +func TestCompletionInstall_Idempotent(t *testing.T) { + home := setupHome(t) + t.Setenv("SHELL", "/bin/bash") + + for i := 0; i < 2; i++ { + if err := runCompletionInstall(nil, nil); err != nil { + t.Fatalf("call %d: unexpected error: %v", i, err) + } + } + + content, err := os.ReadFile(filepath.Join(home, ".bashrc")) + if err != nil { + t.Fatalf(".bashrc was not created: %v", err) + } + if n := strings.Count(string(content), `eval "$(ovhcloud completion bash)"`); n != 1 { + t.Errorf("expected the completion line exactly once, got %d:\n%s", n, content) + } +} + +func TestCompletionInstall_PreservesExistingContent(t *testing.T) { + home := setupHome(t) + t.Setenv("SHELL", "/bin/zsh") + + rcFile := filepath.Join(home, ".zshrc") + existing := "export EDITOR=vim\nalias ll='ls -la'\n" + if err := os.WriteFile(rcFile, []byte(existing), 0o644); err != nil { + t.Fatalf("failed to seed .zshrc: %v", err) + } + + if err := runCompletionInstall(nil, nil); err != nil { + t.Fatalf("unexpected error: %v", err) + } + + content, err := os.ReadFile(rcFile) + if err != nil { + t.Fatalf("failed to read .zshrc: %v", err) + } + if !strings.Contains(string(content), existing) { + t.Errorf("existing .zshrc content was lost:\n%s", content) + } + if !strings.Contains(string(content), `eval "$(ovhcloud completion zsh)"`) { + t.Errorf("completion line was not appended:\n%s", content) + } +} + +func TestCompletionInstall_FishWithXDG(t *testing.T) { + home := t.TempDir() + t.Setenv("HOME", home) + t.Setenv("SHELL", "/usr/bin/fish") + + xdg := t.TempDir() + t.Setenv("XDG_CONFIG_HOME", xdg) + + if err := runCompletionInstall(nil, nil); err != nil { + t.Fatalf("unexpected error: %v", err) + } + + destFile := filepath.Join(xdg, "fish", "completions", "ovhcloud.fish") + info, err := os.Stat(destFile) + if err != nil { + t.Fatalf("fish completion file was not created at %s: %v", destFile, err) + } + if info.Size() == 0 { + t.Errorf("fish completion file is empty") + } +} + +func TestCompletionInstall_FishDefaultConfigDir(t *testing.T) { + home := setupHome(t) // XDG_CONFIG_HOME cleared → falls back to ~/.config + t.Setenv("SHELL", "/usr/bin/fish") + + if err := runCompletionInstall(nil, nil); err != nil { + t.Fatalf("unexpected error: %v", err) + } + + destFile := filepath.Join(home, ".config", "fish", "completions", "ovhcloud.fish") + if _, err := os.Stat(destFile); err != nil { + t.Fatalf("fish completion file was not created at %s: %v", destFile, err) + } +} + +func TestCompletionInstall_UnsupportedShell(t *testing.T) { + setupHome(t) + t.Setenv("SHELL", "/usr/bin/tcsh") + + err := runCompletionInstall(nil, nil) + if err == nil { + t.Fatal("expected an error for an unsupported shell, got nil") + } + if !strings.Contains(err.Error(), "unsupported shell") { + t.Errorf("unexpected error message: %v", err) + } +} + +func TestCompletionInstall_EmptyShell(t *testing.T) { + setupHome(t) + t.Setenv("SHELL", "") + + err := runCompletionInstall(nil, nil) + if err == nil { + t.Fatal("expected an error when SHELL is unset, got nil") + } + if !strings.Contains(err.Error(), "SHELL environment variable is not set") { + t.Errorf("unexpected error message: %v", err) + } +} diff --git a/internal/cmd/dedicatedceph.go b/internal/cmd/dedicatedceph.go index abaafe4a..93ac9141 100644 --- a/internal/cmd/dedicatedceph.go +++ b/internal/cmd/dedicatedceph.go @@ -5,6 +5,7 @@ package cmd import ( + "github.com/ovh/ovhcloud-cli/internal/completion" "github.com/ovh/ovhcloud-cli/internal/services/dedicatedceph" "github.com/spf13/cobra" ) @@ -26,18 +27,20 @@ func init() { // Command to get a single DedicatedCeph dedicatedcephCmd.AddCommand(&cobra.Command{ - Use: "get ", - Short: "Retrieve information of a specific Dedicated Ceph", - Args: cobra.ExactArgs(1), - Run: dedicatedceph.GetDedicatedCeph, + Use: "get ", + Short: "Retrieve information of a specific Dedicated Ceph", + Args: cobra.ExactArgs(1), + ValidArgsFunction: completion.ServiceList("/v1/dedicated/ceph"), + Run: dedicatedceph.GetDedicatedCeph, }) // Command to update a single DedicatedCeph editCmd := &cobra.Command{ - Use: "edit ", - Short: "Edit the given Dedicated Ceph", - Args: cobra.ExactArgs(1), - Run: dedicatedceph.EditDedicatedCeph, + Use: "edit ", + Short: "Edit the given Dedicated Ceph", + Args: cobra.ExactArgs(1), + ValidArgsFunction: completion.ServiceList("/v1/dedicated/ceph"), + Run: dedicatedceph.EditDedicatedCeph, } editCmd.Flags().StringVar(&dedicatedceph.DedicatedCephSpec.CrushTunables, "crush-tunables", "", "Tunables of cluster (ARGONAUT, BOBTAIL, DEFAULT, FIREFLY, HAMMER, JEWEL, LEGACY, OPTIMAL)") editCmd.Flags().StringVar(&dedicatedceph.DedicatedCephSpec.Label, "label", "", "Name of the cluster") diff --git a/internal/cmd/dedicatedcloud.go b/internal/cmd/dedicatedcloud.go index 9d9baf39..96e3aa00 100644 --- a/internal/cmd/dedicatedcloud.go +++ b/internal/cmd/dedicatedcloud.go @@ -5,6 +5,7 @@ package cmd import ( + "github.com/ovh/ovhcloud-cli/internal/completion" "github.com/ovh/ovhcloud-cli/internal/services/dedicatedcloud" "github.com/spf13/cobra" ) @@ -26,10 +27,11 @@ func init() { // Command to get a single DedicatedCloud dedicatedcloudCmd.AddCommand(&cobra.Command{ - Use: "get ", - Short: "Retrieve information of a specific DedicatedCloud", - Args: cobra.ExactArgs(1), - Run: dedicatedcloud.GetDedicatedCloud, + Use: "get ", + Short: "Retrieve information of a specific DedicatedCloud", + Args: cobra.ExactArgs(1), + ValidArgsFunction: completion.ServiceList("/v1/dedicatedCloud"), + Run: dedicatedcloud.GetDedicatedCloud, }) rootCmd.AddCommand(dedicatedcloudCmd) diff --git a/internal/cmd/dedicatedcluster.go b/internal/cmd/dedicatedcluster.go index 09f52dad..72fc8722 100644 --- a/internal/cmd/dedicatedcluster.go +++ b/internal/cmd/dedicatedcluster.go @@ -5,6 +5,7 @@ package cmd import ( + "github.com/ovh/ovhcloud-cli/internal/completion" "github.com/ovh/ovhcloud-cli/internal/services/dedicatedcluster" "github.com/spf13/cobra" ) @@ -26,10 +27,11 @@ func init() { // Command to get a single DedicatedCluster dedicatedclusterCmd.AddCommand(&cobra.Command{ - Use: "get ", - Short: "Retrieve information of a specific DedicatedCluster", - Args: cobra.ExactArgs(1), - Run: dedicatedcluster.GetDedicatedCluster, + Use: "get ", + Short: "Retrieve information of a specific DedicatedCluster", + Args: cobra.ExactArgs(1), + ValidArgsFunction: completion.ServiceList("/v1/dedicated/cluster"), + Run: dedicatedcluster.GetDedicatedCluster, }) rootCmd.AddCommand(dedicatedclusterCmd) diff --git a/internal/cmd/dedicatednasha.go b/internal/cmd/dedicatednasha.go index e8140aef..81203b47 100644 --- a/internal/cmd/dedicatednasha.go +++ b/internal/cmd/dedicatednasha.go @@ -5,6 +5,7 @@ package cmd import ( + "github.com/ovh/ovhcloud-cli/internal/completion" "github.com/ovh/ovhcloud-cli/internal/services/dedicatednasha" "github.com/spf13/cobra" ) @@ -26,18 +27,20 @@ func init() { // Command to get a single DedicatedNasHA dedicatednashaCmd.AddCommand(&cobra.Command{ - Use: "get ", - Short: "Retrieve information of a specific Dedicated NasHA", - Args: cobra.ExactArgs(1), - Run: dedicatednasha.GetDedicatedNasHA, + Use: "get ", + Short: "Retrieve information of a specific Dedicated NasHA", + Args: cobra.ExactArgs(1), + ValidArgsFunction: completion.ServiceList("/v1/dedicated/nasha"), + Run: dedicatednasha.GetDedicatedNasHA, }) // Command to update a single DedicatedNasHA editDedicatednashaCmd := &cobra.Command{ - Use: "edit ", - Short: "Edit the given Dedicated NasHA", - Args: cobra.ExactArgs(1), - Run: dedicatednasha.EditDedicatedNasHA, + Use: "edit ", + Short: "Edit the given Dedicated NasHA", + Args: cobra.ExactArgs(1), + ValidArgsFunction: completion.ServiceList("/v1/dedicated/nasha"), + Run: dedicatednasha.EditDedicatedNasHA, } editDedicatednashaCmd.Flags().StringVar(&dedicatednasha.DedicatedNasHASpec.CustomName, "custom-name", "", "Custom name for the Dedicated NasHA") editDedicatednashaCmd.Flags().BoolVar(&dedicatednasha.DedicatedNasHASpec.Monitored, "monitored", false, "Send an email to customer if any issue is detected") diff --git a/internal/cmd/domainname.go b/internal/cmd/domainname.go index 2c9e3ef4..aabbb361 100644 --- a/internal/cmd/domainname.go +++ b/internal/cmd/domainname.go @@ -5,6 +5,7 @@ package cmd import ( + "github.com/ovh/ovhcloud-cli/internal/completion" "github.com/ovh/ovhcloud-cli/internal/services/domainname" "github.com/spf13/cobra" ) @@ -26,18 +27,20 @@ func init() { // Command to get a single DomainName domainnameCmd.AddCommand(&cobra.Command{ - Use: "get ", - Short: "Retrieve information of a specific domain name", - Args: cobra.ExactArgs(1), - Run: domainname.GetDomainName, + Use: "get ", + Short: "Retrieve information of a specific domain name", + Args: cobra.ExactArgs(1), + ValidArgsFunction: completion.ServiceList("/v1/domain"), + Run: domainname.GetDomainName, }) // Command to update a single DomainName editDomainNameCmd := &cobra.Command{ - Use: "edit ", - Short: "Edit the given domain name service", - Args: cobra.ExactArgs(1), - Run: domainname.EditDomainName, + Use: "edit ", + Short: "Edit the given domain name service", + Args: cobra.ExactArgs(1), + ValidArgsFunction: completion.ServiceList("/v1/domain"), + Run: domainname.EditDomainName, } editDomainNameCmd.Flags().StringVar(&domainname.DomainSpec.NameServerType, "name-server-type", "", "Type of name server (anycast, dedicated, empty, external, hold, hosted, hosting, mixed, parking)") editDomainNameCmd.Flags().StringVar(&domainname.DomainSpec.TranferLockStatus, "transfer-lock-status", "", "Transfer lock status (locked, locking, unavailable, unlocked, unlocking)") diff --git a/internal/cmd/domainzone.go b/internal/cmd/domainzone.go index 273b418e..e271d344 100644 --- a/internal/cmd/domainzone.go +++ b/internal/cmd/domainzone.go @@ -6,6 +6,7 @@ package cmd import ( "github.com/ovh/ovhcloud-cli/internal/assets" + "github.com/ovh/ovhcloud-cli/internal/completion" "github.com/ovh/ovhcloud-cli/internal/services/domainzone" "github.com/spf13/cobra" ) @@ -27,17 +28,19 @@ func init() { // Command to get a single DomainZone domainzoneCmd.AddCommand(&cobra.Command{ - Use: "get ", - Short: "Retrieve information of a specific domain zone", - Args: cobra.ExactArgs(1), - Run: domainzone.GetDomainZone, + Use: "get ", + Short: "Retrieve information of a specific domain zone", + Args: cobra.ExactArgs(1), + ValidArgsFunction: completion.ServiceList("/v1/domain/zone"), + Run: domainzone.GetDomainZone, }) domainzoneCmd.AddCommand(&cobra.Command{ - Use: "refresh ", - Short: "Refresh the given zone", - Args: cobra.ExactArgs(1), - Run: domainzone.RefreshZone, + Use: "refresh ", + Short: "Refresh the given zone", + Args: cobra.ExactArgs(1), + ValidArgsFunction: completion.ServiceList("/v1/domain/zone"), + Run: domainzone.RefreshZone, }) domainZoneRecordCmd := &cobra.Command{ @@ -47,27 +50,30 @@ func init() { domainzoneCmd.AddCommand(domainZoneRecordCmd) domainZoneRecordListCmd := &cobra.Command{ - Use: "list ", - Aliases: []string{"ls"}, - Short: "List all DNS records from your zone", - Args: cobra.ExactArgs(1), - Run: domainzone.ListRecords, + Use: "list ", + Aliases: []string{"ls"}, + Short: "List all DNS records from your zone", + Args: cobra.ExactArgs(1), + ValidArgsFunction: completion.ServiceList("/v1/domain/zone"), + Run: domainzone.ListRecords, } domainZoneRecordCmd.AddCommand(withFilterFlag(domainZoneRecordListCmd)) domainZoneRecordGetCmd := &cobra.Command{ - Use: "get ", - Short: "Get a single DNS record from your zone", - Args: cobra.ExactArgs(2), - Run: domainzone.GetRecord, + Use: "get ", + Short: "Get a single DNS record from your zone", + Args: cobra.ExactArgs(2), + ValidArgsFunction: completion.ServiceList("/v1/domain/zone"), + Run: domainzone.GetRecord, } domainZoneRecordCmd.AddCommand(domainZoneRecordGetCmd) domainZoneRecordPostCmd := &cobra.Command{ - Use: "create ", - Short: "Create a single DNS record in your zone", - Args: cobra.ExactArgs(1), - Run: domainzone.CreateRecord, + Use: "create ", + Short: "Create a single DNS record in your zone", + Args: cobra.ExactArgs(1), + ValidArgsFunction: completion.ServiceList("/v1/domain/zone"), + Run: domainzone.CreateRecord, } domainZoneRecordPostCmd.Flags().StringVar(&domainzone.CreateRecordSpec.FieldType, "field-type", "", "Record type (A, AAAA, CAA, CNAME, DKIM, DMARC, DNAME, HTTPS, LOC, MX, NAPTR, NS, PTR, RP, SPF, SRV, SSHFP, SVCB, TLSA, TXT)") domainZoneRecordPostCmd.Flags().StringVar(&domainzone.CreateRecordSpec.SubDomain, "sub-domain", "", "Record subDomain") @@ -81,10 +87,11 @@ func init() { domainZoneRecordCmd.AddCommand(domainZoneRecordPostCmd) domainZoneRecordPutCmd := &cobra.Command{ - Use: "update ", - Short: "Update a single DNS record from your zone", - Args: cobra.ExactArgs(2), - Run: domainzone.UpdateRecord, + Use: "update ", + Short: "Update a single DNS record from your zone", + Args: cobra.ExactArgs(2), + ValidArgsFunction: completion.ServiceList("/v1/domain/zone"), + Run: domainzone.UpdateRecord, } domainZoneRecordPutCmd.Flags().StringVar(&domainzone.UpdateRecordSpec.SubDomain, "sub-domain", "", "Subdomain to update") domainZoneRecordPutCmd.Flags().StringVar(&domainzone.UpdateRecordSpec.Target, "target", "", "New target to apply") @@ -97,10 +104,11 @@ func init() { domainZoneRecordCmd.AddCommand(domainZoneRecordPutCmd) domainZoneRecordDeleteCmd := &cobra.Command{ - Use: "delete ", - Short: "Delete a single DNS record from your zone", - Args: cobra.ExactArgs(2), - Run: domainzone.DeleteRecord, + Use: "delete ", + Short: "Delete a single DNS record from your zone", + Args: cobra.ExactArgs(2), + ValidArgsFunction: completion.ServiceList("/v1/domain/zone"), + Run: domainzone.DeleteRecord, } domainZoneRecordCmd.AddCommand(domainZoneRecordDeleteCmd) diff --git a/internal/cmd/emaildomain.go b/internal/cmd/emaildomain.go index 5d7418b6..6614cd63 100644 --- a/internal/cmd/emaildomain.go +++ b/internal/cmd/emaildomain.go @@ -6,6 +6,7 @@ package cmd import ( "github.com/ovh/ovhcloud-cli/internal/assets" + "github.com/ovh/ovhcloud-cli/internal/completion" "github.com/ovh/ovhcloud-cli/internal/services/emaildomain" "github.com/spf13/cobra" ) @@ -27,10 +28,11 @@ func init() { // Command to get a single EmailDomain emaildomainCmd.AddCommand(&cobra.Command{ - Use: "get ", - Short: "Retrieve information of a specific Email Domain", - Args: cobra.ExactArgs(1), - Run: emaildomain.GetEmailDomain, + Use: "get ", + Short: "Retrieve information of a specific Email Domain", + Args: cobra.ExactArgs(1), + ValidArgsFunction: completion.ServiceList("/v1/email/domain"), + Run: emaildomain.GetEmailDomain, }) // Redirection subcommand @@ -42,28 +44,31 @@ func init() { // List redirections emaildomainRedirectionListCmd := &cobra.Command{ - Use: "list ", - Aliases: []string{"ls"}, - Short: "List all email redirections for a domain", - Args: cobra.ExactArgs(1), - Run: emaildomain.ListRedirections, + Use: "list ", + Aliases: []string{"ls"}, + Short: "List all email redirections for a domain", + Args: cobra.ExactArgs(1), + ValidArgsFunction: completion.ServiceList("/v1/email/domain"), + Run: emaildomain.ListRedirections, } emaildomainRedirectionCmd.AddCommand(withFilterFlag(emaildomainRedirectionListCmd)) // Get a specific redirection emaildomainRedirectionCmd.AddCommand(&cobra.Command{ - Use: "get ", - Short: "Get details of a specific email redirection", - Args: cobra.ExactArgs(2), - Run: emaildomain.GetRedirection, + Use: "get ", + Short: "Get details of a specific email redirection", + Args: cobra.ExactArgs(2), + ValidArgsFunction: completion.ServiceList("/v1/email/domain"), + Run: emaildomain.GetRedirection, }) // Create redirection createRedirectionCmd := &cobra.Command{ - Use: "create ", - Short: "Create a new email redirection", - Args: cobra.ExactArgs(1), - Run: emaildomain.CreateRedirection, + Use: "create ", + Short: "Create a new email redirection", + Args: cobra.ExactArgs(1), + ValidArgsFunction: completion.ServiceList("/v1/email/domain"), + Run: emaildomain.CreateRedirection, } createRedirectionCmd.Flags().StringVar(&emaildomain.RedirectionSpec.From, "from", "", "Source email address (e.g., alias@domain.com)") createRedirectionCmd.Flags().StringVar(&emaildomain.RedirectionSpec.To, "to", "", "Destination email address") @@ -77,10 +82,11 @@ func init() { // Delete redirection emaildomainRedirectionCmd.AddCommand(&cobra.Command{ - Use: "delete ", - Short: "Delete an email redirection", - Args: cobra.ExactArgs(2), - Run: emaildomain.DeleteRedirection, + Use: "delete ", + Short: "Delete an email redirection", + Args: cobra.ExactArgs(2), + ValidArgsFunction: completion.ServiceList("/v1/email/domain"), + Run: emaildomain.DeleteRedirection, }) rootCmd.AddCommand(emaildomainCmd) diff --git a/internal/cmd/emailmxplan.go b/internal/cmd/emailmxplan.go index b4f4a518..b102a69b 100644 --- a/internal/cmd/emailmxplan.go +++ b/internal/cmd/emailmxplan.go @@ -5,6 +5,7 @@ package cmd import ( + "github.com/ovh/ovhcloud-cli/internal/completion" "github.com/ovh/ovhcloud-cli/internal/services/emailmxplan" "github.com/spf13/cobra" ) @@ -26,18 +27,20 @@ func init() { // Command to get a single EmailMXPlan emailmxplanCmd.AddCommand(&cobra.Command{ - Use: "get ", - Short: "Retrieve information of a specific Email MXPlan", - Args: cobra.ExactArgs(1), - Run: emailmxplan.GetEmailMXPlan, + Use: "get ", + Short: "Retrieve information of a specific Email MXPlan", + Args: cobra.ExactArgs(1), + ValidArgsFunction: completion.ServiceList("/v1/email/mxplan"), + Run: emailmxplan.GetEmailMXPlan, }) // Command to update a single EmailMXPlan emailmxplanEditCmd := &cobra.Command{ - Use: "edit ", - Short: "Edit the given Email MXPlan", - Args: cobra.ExactArgs(1), - Run: emailmxplan.EditEmailMXPlan, + Use: "edit ", + Short: "Edit the given Email MXPlan", + Args: cobra.ExactArgs(1), + ValidArgsFunction: completion.ServiceList("/v1/email/mxplan"), + Run: emailmxplan.EditEmailMXPlan, } emailmxplanEditCmd.Flags().BoolVar(&emailmxplan.EmailMXPlanSpec.ComplexityEnabled, "complexity-enabled", false, "Enable policy for strong and secure passwords") emailmxplanEditCmd.Flags().StringVar(&emailmxplan.EmailMXPlanSpec.DisplayName, "display-name", "", "Service displayName") diff --git a/internal/cmd/emailpro.go b/internal/cmd/emailpro.go index defa9254..1859aa2a 100644 --- a/internal/cmd/emailpro.go +++ b/internal/cmd/emailpro.go @@ -5,6 +5,7 @@ package cmd import ( + "github.com/ovh/ovhcloud-cli/internal/completion" "github.com/ovh/ovhcloud-cli/internal/services/emailpro" "github.com/spf13/cobra" ) @@ -26,18 +27,20 @@ func init() { // Command to get a single EmailPro emailproCmd.AddCommand(&cobra.Command{ - Use: "get ", - Short: "Retrieve information of a specific EmailPro", - Args: cobra.ExactArgs(1), - Run: emailpro.GetEmailPro, + Use: "get ", + Short: "Retrieve information of a specific EmailPro", + Args: cobra.ExactArgs(1), + ValidArgsFunction: completion.ServiceList("/v1/email/pro"), + Run: emailpro.GetEmailPro, }) // Command to update a single EmailPro editEmailProCmd := &cobra.Command{ - Use: "edit ", - Short: "Edit the given EmailPro", - Args: cobra.ExactArgs(1), - Run: emailpro.EditEmailPro, + Use: "edit ", + Short: "Edit the given EmailPro", + Args: cobra.ExactArgs(1), + ValidArgsFunction: completion.ServiceList("/v1/email/pro"), + Run: emailpro.EditEmailPro, } emailproCmd.Flags().BoolVar(&emailpro.EmailProSpec.ComplexityEnabled, "complexity-enabled", false, "Enable policy for strong and secure passwords") emailproCmd.Flags().StringVar(&emailpro.EmailProSpec.DisplayName, "display-name", "", "Service displayName") diff --git a/internal/cmd/hostingprivatedatabase.go b/internal/cmd/hostingprivatedatabase.go index 956b9232..529cdd2b 100644 --- a/internal/cmd/hostingprivatedatabase.go +++ b/internal/cmd/hostingprivatedatabase.go @@ -5,6 +5,7 @@ package cmd import ( + "github.com/ovh/ovhcloud-cli/internal/completion" "github.com/ovh/ovhcloud-cli/internal/services/hostingprivatedatabase" "github.com/spf13/cobra" ) @@ -26,18 +27,20 @@ func init() { // Command to get a single HostingPrivateDatabase hostingprivatedatabaseCmd.AddCommand(&cobra.Command{ - Use: "get ", - Short: "Retrieve information of a specific HostingPrivateDatabase", - Args: cobra.ExactArgs(1), - Run: hostingprivatedatabase.GetHostingPrivateDatabase, + Use: "get ", + Short: "Retrieve information of a specific HostingPrivateDatabase", + Args: cobra.ExactArgs(1), + ValidArgsFunction: completion.ServiceList("/v1/hosting/privateDatabase"), + Run: hostingprivatedatabase.GetHostingPrivateDatabase, }) // Command to update a single HostingPrivateDatabase hostingprivatedatabaseEditCmd := &cobra.Command{ - Use: "edit ", - Short: "Edit the given HostingPrivateDatabase service", - Args: cobra.ExactArgs(1), - Run: hostingprivatedatabase.EditHostingPrivateDatabase, + Use: "edit ", + Short: "Edit the given HostingPrivateDatabase service", + Args: cobra.ExactArgs(1), + ValidArgsFunction: completion.ServiceList("/v1/hosting/privateDatabase"), + Run: hostingprivatedatabase.EditHostingPrivateDatabase, } hostingprivatedatabaseEditCmd.Flags().StringVar(&hostingprivatedatabase.HostingPrivateDatabaseDisplayName, "display-name", "", "Display name of the HostingPrivateDatabase") addInteractiveEditorFlag(hostingprivatedatabaseEditCmd) diff --git a/internal/cmd/iam.go b/internal/cmd/iam.go index 972459b6..dd2b2111 100644 --- a/internal/cmd/iam.go +++ b/internal/cmd/iam.go @@ -6,6 +6,7 @@ package cmd import ( "github.com/ovh/ovhcloud-cli/internal/assets" + "github.com/ovh/ovhcloud-cli/internal/completion" "github.com/ovh/ovhcloud-cli/internal/services/iam" "github.com/spf13/cobra" ) @@ -31,10 +32,11 @@ func init() { iamPolicyCmd.AddCommand(iamPolicyListCmd) iamPolicyCmd.AddCommand(&cobra.Command{ - Use: "get ", - Short: "Get a specific IAM policy", - Run: iam.GetIAMPolicy, - Args: cobra.ExactArgs(1), + Use: "get ", + Short: "Get a specific IAM policy", + ValidArgsFunction: completion.ServiceList("/v2/iam/policy"), + Run: iam.GetIAMPolicy, + Args: cobra.ExactArgs(1), }) iamPolicyCreateCmd := getGenericCreateCmd( @@ -55,10 +57,11 @@ func init() { iamPolicyCmd.AddCommand(iamPolicyCreateCmd) iamPolicyEditCmd := &cobra.Command{ - Use: "edit ", - Short: "Edit specific IAM policy", - Run: iam.EditIAMPolicy, - Args: cobra.ExactArgs(1), + Use: "edit ", + Short: "Edit specific IAM policy", + ValidArgsFunction: completion.ServiceList("/v2/iam/policy"), + Run: iam.EditIAMPolicy, + Args: cobra.ExactArgs(1), } iamPolicyEditCmd.Flags().StringVar(&iam.IAMPolicySpec.Name, "name", "", "Name of the policy") iamPolicyEditCmd.Flags().StringVar(&iam.IAMPolicySpec.Description, "description", "", "Description of the policy") @@ -73,10 +76,11 @@ func init() { iamPolicyCmd.AddCommand(iamPolicyEditCmd) iamPolicyCmd.AddCommand(&cobra.Command{ - Use: "delete ", - Short: "Delete a specific IAM policy", - Run: iam.DeleteIAMPolicy, - Args: cobra.ExactArgs(1), + Use: "delete ", + Short: "Delete a specific IAM policy", + ValidArgsFunction: completion.ServiceList("/v2/iam/policy"), + Run: iam.DeleteIAMPolicy, + Args: cobra.ExactArgs(1), }) iamPermissionsGroupCmd := &cobra.Command{ @@ -93,17 +97,19 @@ func init() { })) iamPermissionsGroupCmd.AddCommand(&cobra.Command{ - Use: "get ", - Short: "Get a specific IAM permissions group", - Run: iam.GetIAMPermissionsGroup, - Args: cobra.ExactArgs(1), + Use: "get ", + Short: "Get a specific IAM permissions group", + ValidArgsFunction: completion.ServiceList("/v2/iam/permissionsGroup"), + Run: iam.GetIAMPermissionsGroup, + Args: cobra.ExactArgs(1), }) iamPermissionsGroupEditCmd := &cobra.Command{ - Use: "edit ", - Short: "Edit a specific IAM permissions group", - Run: iam.EditIAMPermissionsGroup, - Args: cobra.ExactArgs(1), + Use: "edit ", + Short: "Edit a specific IAM permissions group", + ValidArgsFunction: completion.ServiceList("/v2/iam/permissionsGroup"), + Run: iam.EditIAMPermissionsGroup, + Args: cobra.ExactArgs(1), } iamPermissionsGroupEditCmd.Flags().StringVar(&iam.IAMPolicySpec.Name, "name", "", "Name of the policy") iamPermissionsGroupEditCmd.Flags().StringVar(&iam.IAMPolicySpec.Description, "description", "", "Description of the policy") @@ -157,17 +163,19 @@ func init() { })) iamResourceGroupCmd.AddCommand(&cobra.Command{ - Use: "get ", - Short: "Get a specific IAM resource group", - Run: iam.GetIAMResourceGroup, - Args: cobra.ExactArgs(1), + Use: "get ", + Short: "Get a specific IAM resource group", + ValidArgsFunction: completion.ServiceList("/v2/iam/resourceGroup"), + Run: iam.GetIAMResourceGroup, + Args: cobra.ExactArgs(1), }) iamResourceGroupEditCmd := &cobra.Command{ - Use: "edit ", - Short: "Edit a specific IAM resource group", - Run: iam.EditIAMResourceGroup, - Args: cobra.ExactArgs(1), + Use: "edit ", + Short: "Edit a specific IAM resource group", + ValidArgsFunction: completion.ServiceList("/v2/iam/resourceGroup"), + Run: iam.EditIAMResourceGroup, + Args: cobra.ExactArgs(1), } iamResourceGroupEditCmd.Flags().StringVar(&iam.IAMPolicySpec.Name, "name", "", "Name of the resource group") iamResourceGroupEditCmd.Flags().StringSliceVar(&iam.IAMPolicySpec.ResourcesURNs, "resource", nil, "List of resource URNs to include in the group") @@ -189,20 +197,22 @@ func init() { })) iamUserCmd.AddCommand(&cobra.Command{ - Use: "get ", - Short: "Get a specific IAM user", - Run: iam.GetUser, - Args: cobra.ExactArgs(1), + Use: "get ", + Short: "Get a specific IAM user", + ValidArgsFunction: completion.ServiceList("/v1/me/identity/user"), + Run: iam.GetUser, + Args: cobra.ExactArgs(1), }) iamUserCmd.AddCommand(getUserCreateCmd()) iamUserCmd.AddCommand(getUserEditCmd()) iamUserCmd.AddCommand(&cobra.Command{ - Use: "delete ", - Short: "Delete a specific IAM user", - Run: iam.DeleteUser, - Args: cobra.ExactArgs(1), + Use: "delete ", + Short: "Delete a specific IAM user", + ValidArgsFunction: completion.ServiceList("/v1/me/identity/user"), + Run: iam.DeleteUser, + Args: cobra.ExactArgs(1), }) tokenCmd := &cobra.Command{ @@ -212,18 +222,20 @@ func init() { iamUserCmd.AddCommand(tokenCmd) tokenCmd.AddCommand(withFilterFlag(&cobra.Command{ - Use: "list ", - Aliases: []string{"ls"}, - Short: "List tokens of a specific IAM user", - Run: iam.ListUserTokens, - Args: cobra.ExactArgs(1), + Use: "list ", + Aliases: []string{"ls"}, + Short: "List tokens of a specific IAM user", + ValidArgsFunction: completion.ServiceList("/v1/me/identity/user"), + Run: iam.ListUserTokens, + Args: cobra.ExactArgs(1), })) tokenCmd.AddCommand(&cobra.Command{ - Use: "get ", - Short: "Get a specific token of an IAM user", - Run: iam.GetUserToken, - Args: cobra.ExactArgs(2), + Use: "get ", + Short: "Get a specific token of an IAM user", + ValidArgsFunction: completion.ServiceList("/v1/me/identity/user"), + Run: iam.GetUserToken, + Args: cobra.ExactArgs(2), }) tokenCreateCmd := getGenericCreateCmd( @@ -238,10 +250,11 @@ func init() { tokenCmd.AddCommand(tokenCreateCmd) tokenCmd.AddCommand(&cobra.Command{ - Use: "delete ", - Short: "Delete a specific token of an IAM user", - Run: iam.DeleteUserToken, - Args: cobra.ExactArgs(2), + Use: "delete ", + Short: "Delete a specific token of an IAM user", + ValidArgsFunction: completion.ServiceList("/v1/me/identity/user"), + Run: iam.DeleteUserToken, + Args: cobra.ExactArgs(2), }) rootCmd.AddCommand(iamCmd) @@ -348,8 +361,9 @@ There are three ways to define the editing parameters: ovhcloud iam user edit --editor --description "New description" `, - Run: iam.EditUser, - Args: cobra.ExactArgs(1), + ValidArgsFunction: completion.ServiceList("/v1/me/identity/user"), + Run: iam.EditUser, + Args: cobra.ExactArgs(1), } userEditCmd.Flags().StringVar(&iam.UserSpec.Email, "email", "", "Email of the user") diff --git a/internal/cmd/ip.go b/internal/cmd/ip.go index a29b424e..364d62d3 100644 --- a/internal/cmd/ip.go +++ b/internal/cmd/ip.go @@ -6,6 +6,7 @@ package cmd import ( "github.com/ovh/ovhcloud-cli/internal/assets" + "github.com/ovh/ovhcloud-cli/internal/completion" "github.com/ovh/ovhcloud-cli/internal/services/ip" "github.com/spf13/cobra" ) @@ -27,18 +28,20 @@ func init() { // Command to get a single Ip ipCmd.AddCommand(&cobra.Command{ - Use: "get ", - Short: "Retrieve information of a specific Ip", - Args: cobra.ExactArgs(1), - Run: ip.GetIp, + Use: "get ", + Short: "Retrieve information of a specific Ip", + Args: cobra.ExactArgs(1), + ValidArgsFunction: completion.ServiceList("/v1/ip"), + Run: ip.GetIp, }) // Command to update a single Ip ipEditCmd := &cobra.Command{ - Use: "edit ", - Short: "Edit the given IP", - Args: cobra.ExactArgs(1), - Run: ip.EditIp, + Use: "edit ", + Short: "Edit the given IP", + Args: cobra.ExactArgs(1), + ValidArgsFunction: completion.ServiceList("/v1/ip"), + Run: ip.EditIp, } ipEditCmd.Flags().StringVar(&ip.IPSpec.Description, "description", "", "Description of the IP") addInteractiveEditorFlag(ipEditCmd) @@ -51,26 +54,29 @@ func init() { ipCmd.AddCommand(ipReverseCmd) ipReverseSetCmd := &cobra.Command{ - Use: "set ", - Short: "Set reverse on the given IP", - Args: cobra.ExactArgs(3), - Run: ip.IpSetReverse, + Use: "set ", + Short: "Set reverse on the given IP", + Args: cobra.ExactArgs(3), + ValidArgsFunction: completion.ServiceList("/v1/ip"), + Run: ip.IpSetReverse, } ipReverseCmd.AddCommand(ipReverseSetCmd) ipReverseGetCmd := &cobra.Command{ - Use: "get ", - Short: "List reverse on the given IP range", - Args: cobra.ExactArgs(1), - Run: ip.IpGetReverse, + Use: "get ", + Short: "List reverse on the given IP range", + Args: cobra.ExactArgs(1), + ValidArgsFunction: completion.ServiceList("/v1/ip"), + Run: ip.IpGetReverse, } ipReverseCmd.AddCommand(ipReverseGetCmd) ipReverseDeleteCmd := &cobra.Command{ - Use: "delete ", - Short: "Delete reverse on the given IP", - Args: cobra.ExactArgs(2), - Run: ip.IpDeleteReverse, + Use: "delete ", + Short: "Delete reverse on the given IP", + Args: cobra.ExactArgs(2), + ValidArgsFunction: completion.ServiceList("/v1/ip"), + Run: ip.IpDeleteReverse, } ipReverseCmd.AddCommand(ipReverseDeleteCmd) @@ -82,46 +88,52 @@ func init() { ipCmd.AddCommand(ipFirewallCmd) ipFirewallCmd.AddCommand(withFilterFlag(&cobra.Command{ - Use: "list ", - Aliases: []string{"ls"}, - Short: "List IPs registered on the firewall", - Args: cobra.ExactArgs(1), - Run: ip.ListFirewall, + Use: "list ", + Aliases: []string{"ls"}, + Short: "List IPs registered on the firewall", + Args: cobra.ExactArgs(1), + ValidArgsFunction: completion.ServiceList("/v1/ip"), + Run: ip.ListFirewall, })) ipFirewallCmd.AddCommand(&cobra.Command{ - Use: "add ", - Short: "Add an IP to the firewall", - Args: cobra.ExactArgs(2), - Run: ip.AddFirewall, + Use: "add ", + Short: "Add an IP to the firewall", + Args: cobra.ExactArgs(2), + ValidArgsFunction: completion.ServiceList("/v1/ip"), + Run: ip.AddFirewall, }) ipFirewallCmd.AddCommand(&cobra.Command{ - Use: "get ", - Short: "Get firewall status for a specific IP", - Args: cobra.ExactArgs(2), - Run: ip.GetFirewall, + Use: "get ", + Short: "Get firewall status for a specific IP", + Args: cobra.ExactArgs(2), + ValidArgsFunction: completion.ServiceList("/v1/ip"), + Run: ip.GetFirewall, }) ipFirewallCmd.AddCommand(&cobra.Command{ - Use: "enable ", - Short: "Enable the firewall on the given IP", - Args: cobra.ExactArgs(2), - Run: ip.EnableFirewall, + Use: "enable ", + Short: "Enable the firewall on the given IP", + Args: cobra.ExactArgs(2), + ValidArgsFunction: completion.ServiceList("/v1/ip"), + Run: ip.EnableFirewall, }) ipFirewallCmd.AddCommand(&cobra.Command{ - Use: "disable ", - Short: "Disable the firewall on the given IP", - Args: cobra.ExactArgs(2), - Run: ip.DisableFirewall, + Use: "disable ", + Short: "Disable the firewall on the given IP", + Args: cobra.ExactArgs(2), + ValidArgsFunction: completion.ServiceList("/v1/ip"), + Run: ip.DisableFirewall, }) ipFirewallCmd.AddCommand(&cobra.Command{ - Use: "delete ", - Short: "Remove IP and all rules from firewall", - Args: cobra.ExactArgs(2), - Run: ip.DeleteFirewall, + Use: "delete ", + Short: "Remove IP and all rules from firewall", + Args: cobra.ExactArgs(2), + ValidArgsFunction: completion.ServiceList("/v1/ip"), + Run: ip.DeleteFirewall, }) // Firewall rule sub-commands @@ -132,18 +144,20 @@ func init() { ipFirewallCmd.AddCommand(ipFirewallRuleCmd) ipFirewallRuleCmd.AddCommand(withFilterFlag(&cobra.Command{ - Use: "list ", - Aliases: []string{"ls"}, - Short: "List firewall rules for the given IP", - Args: cobra.ExactArgs(2), - Run: ip.ListFirewallRules, + Use: "list ", + Aliases: []string{"ls"}, + Short: "List firewall rules for the given IP", + Args: cobra.ExactArgs(2), + ValidArgsFunction: completion.ServiceList("/v1/ip"), + Run: ip.ListFirewallRules, })) ipFirewallRuleCmd.AddCommand(&cobra.Command{ - Use: "get ", - Short: "Get a specific firewall rule", - Args: cobra.ExactArgs(3), - Run: ip.GetFirewallRule, + Use: "get ", + Short: "Get a specific firewall rule", + Args: cobra.ExactArgs(3), + ValidArgsFunction: completion.ServiceList("/v1/ip"), + Run: ip.GetFirewallRule, }) ipFirewallRuleCreateCmd := &cobra.Command{ @@ -191,10 +205,11 @@ There are three ways to define the creation parameters: ipFirewallRuleCmd.AddCommand(ipFirewallRuleCreateCmd) ipFirewallRuleCmd.AddCommand(&cobra.Command{ - Use: "delete ", - Short: "Delete a firewall rule", - Args: cobra.ExactArgs(3), - Run: ip.DeleteFirewallRule, + Use: "delete ", + Short: "Delete a firewall rule", + Args: cobra.ExactArgs(3), + ValidArgsFunction: completion.ServiceList("/v1/ip"), + Run: ip.DeleteFirewallRule, }) rootCmd.AddCommand(ipCmd) diff --git a/internal/cmd/iploadbalancing.go b/internal/cmd/iploadbalancing.go index f0ba0ad1..d9792142 100644 --- a/internal/cmd/iploadbalancing.go +++ b/internal/cmd/iploadbalancing.go @@ -7,6 +7,7 @@ package cmd import ( _ "embed" + "github.com/ovh/ovhcloud-cli/internal/completion" "github.com/ovh/ovhcloud-cli/internal/services/iploadbalancing" "github.com/spf13/cobra" ) @@ -28,18 +29,20 @@ func init() { // Command to get a single IpLoadbalancing iploadbalancingCmd.AddCommand(&cobra.Command{ - Use: "get ", - Short: "Retrieve information of a specific IpLoadbalancing", - Args: cobra.ExactArgs(1), - Run: iploadbalancing.GetIpLoadbalancing, + Use: "get ", + Short: "Retrieve information of a specific IpLoadbalancing", + Args: cobra.ExactArgs(1), + ValidArgsFunction: completion.ServiceList("/v1/ipLoadbalancing"), + Run: iploadbalancing.GetIpLoadbalancing, }) // Command to update a single IpLoadbalancing iploadbalancingEditCmd := &cobra.Command{ - Use: "edit ", - Short: "Edit the given IpLoadbalancing", - Args: cobra.ExactArgs(1), - Run: iploadbalancing.EditIpLoadbalancing, + Use: "edit ", + Short: "Edit the given IpLoadbalancing", + Args: cobra.ExactArgs(1), + ValidArgsFunction: completion.ServiceList("/v1/ipLoadbalancing"), + Run: iploadbalancing.EditIpLoadbalancing, } iploadbalancingEditCmd.Flags().StringVar(&iploadbalancing.IPLoadbalancingSpec.DisplayName, "display-name", "", "Display name of the load balancer") iploadbalancingEditCmd.Flags().StringVar(&iploadbalancing.IPLoadbalancingSpec.SSLConfiguration, "ssl-configuration", "", "SSL configuration of the load balancer (intermediate, modern)") diff --git a/internal/cmd/ldp.go b/internal/cmd/ldp.go index ecc1ae19..aa9aced9 100644 --- a/internal/cmd/ldp.go +++ b/internal/cmd/ldp.go @@ -5,6 +5,7 @@ package cmd import ( + "github.com/ovh/ovhcloud-cli/internal/completion" "github.com/ovh/ovhcloud-cli/internal/services/ldp" "github.com/spf13/cobra" ) @@ -26,18 +27,20 @@ func init() { // Command to get a single Ldp ldpCmd.AddCommand(&cobra.Command{ - Use: "get ", - Short: "Retrieve information of a specific Ldp", - Args: cobra.ExactArgs(1), - Run: ldp.GetLdp, + Use: "get ", + Short: "Retrieve information of a specific Ldp", + Args: cobra.ExactArgs(1), + ValidArgsFunction: completion.ServiceList("/v1/dbaas/logs"), + Run: ldp.GetLdp, }) // Command to update a single Ldp ldpEditCmd := &cobra.Command{ - Use: "edit ", - Short: "Edit the given Ldp", - Args: cobra.ExactArgs(1), - Run: ldp.EditLdp, + Use: "edit ", + Short: "Edit the given Ldp", + Args: cobra.ExactArgs(1), + ValidArgsFunction: completion.ServiceList("/v1/dbaas/logs"), + Run: ldp.EditLdp, } ldpEditCmd.Flags().StringVar(&ldp.LdpSpec.DisplayName, "display-name", "", "Display name of the LDP") ldpEditCmd.Flags().BoolVar(&ldp.LdpSpec.EnableIAM, "enable-iam", false, "Enable IAM for the LDP") diff --git a/internal/cmd/location.go b/internal/cmd/location.go index dba26ea7..9167534d 100644 --- a/internal/cmd/location.go +++ b/internal/cmd/location.go @@ -5,6 +5,7 @@ package cmd import ( + "github.com/ovh/ovhcloud-cli/internal/completion" "github.com/ovh/ovhcloud-cli/internal/services/location" "github.com/spf13/cobra" ) @@ -26,10 +27,11 @@ func init() { // Command to get a single Location locationCmd.AddCommand(&cobra.Command{ - Use: "get ", - Short: "Retrieve information of a specific Location", - Args: cobra.ExactArgs(1), - Run: location.GetLocation, + Use: "get ", + Short: "Retrieve information of a specific Location", + Args: cobra.ExactArgs(1), + ValidArgsFunction: completion.ServiceList("/v2/location"), + Run: location.GetLocation, }) rootCmd.AddCommand(locationCmd) diff --git a/internal/cmd/nutanix.go b/internal/cmd/nutanix.go index e06cb9b3..88078407 100644 --- a/internal/cmd/nutanix.go +++ b/internal/cmd/nutanix.go @@ -5,6 +5,7 @@ package cmd import ( + "github.com/ovh/ovhcloud-cli/internal/completion" "github.com/ovh/ovhcloud-cli/internal/services/nutanix" "github.com/spf13/cobra" ) @@ -26,10 +27,11 @@ func init() { // Command to get a single Nutanix nutanixCmd.AddCommand(&cobra.Command{ - Use: "get ", - Short: "Retrieve information of a specific Nutanix", - Args: cobra.ExactArgs(1), - Run: nutanix.GetNutanix, + Use: "get ", + Short: "Retrieve information of a specific Nutanix", + Args: cobra.ExactArgs(1), + ValidArgsFunction: completion.ServiceList("/v1/nutanix"), + Run: nutanix.GetNutanix, }) rootCmd.AddCommand(nutanixCmd) diff --git a/internal/cmd/okms.go b/internal/cmd/okms.go index b847aa2d..5848c952 100644 --- a/internal/cmd/okms.go +++ b/internal/cmd/okms.go @@ -5,6 +5,7 @@ package cmd import ( + "github.com/ovh/ovhcloud-cli/internal/completion" "github.com/ovh/ovhcloud-cli/internal/services/okms" "github.com/spf13/cobra" ) @@ -26,10 +27,11 @@ func init() { // Command to get a single Okms okmsCmd.AddCommand(&cobra.Command{ - Use: "get ", - Short: "Retrieve information of a specific OKMS", - Args: cobra.ExactArgs(1), - Run: okms.GetOkms, + Use: "get ", + Short: "Retrieve information of a specific OKMS", + Args: cobra.ExactArgs(1), + ValidArgsFunction: completion.ServiceList("/v2/okms/resource"), + Run: okms.GetOkms, }) rootCmd.AddCommand(okmsCmd) diff --git a/internal/cmd/overthebox.go b/internal/cmd/overthebox.go index 1628e03b..d50a3bbb 100644 --- a/internal/cmd/overthebox.go +++ b/internal/cmd/overthebox.go @@ -5,6 +5,7 @@ package cmd import ( + "github.com/ovh/ovhcloud-cli/internal/completion" "github.com/ovh/ovhcloud-cli/internal/services/overthebox" "github.com/spf13/cobra" ) @@ -26,18 +27,20 @@ func init() { // Command to get a single OverTheBox overtheboxCmd.AddCommand(&cobra.Command{ - Use: "get ", - Short: "Retrieve information of a specific OverTheBox", - Args: cobra.ExactArgs(1), - Run: overthebox.GetOverTheBox, + Use: "get ", + Short: "Retrieve information of a specific OverTheBox", + Args: cobra.ExactArgs(1), + ValidArgsFunction: completion.ServiceList("/v1/overTheBox"), + Run: overthebox.GetOverTheBox, }) // Command to update a single OverTheBox overtheboxEditCmd := &cobra.Command{ - Use: "edit ", - Short: "Edit the given OverTheBox", - Args: cobra.ExactArgs(1), - Run: overthebox.EditOverTheBox, + Use: "edit ", + Short: "Edit the given OverTheBox", + Args: cobra.ExactArgs(1), + ValidArgsFunction: completion.ServiceList("/v1/overTheBox"), + Run: overthebox.EditOverTheBox, } overtheboxEditCmd.Flags().BoolVar(&overthebox.OverTheBoxSpec.AutoUpgrade, "auto-upgrade", false, "Enable device auto upgrade") overtheboxEditCmd.Flags().StringVar(&overthebox.OverTheBoxSpec.CustomerDescription, "customer-description", "", "Customer description") diff --git a/internal/cmd/ovhcloudconnect.go b/internal/cmd/ovhcloudconnect.go index 892c4365..4964b518 100644 --- a/internal/cmd/ovhcloudconnect.go +++ b/internal/cmd/ovhcloudconnect.go @@ -5,6 +5,7 @@ package cmd import ( + "github.com/ovh/ovhcloud-cli/internal/completion" "github.com/ovh/ovhcloud-cli/internal/services/ovhcloudconnect" "github.com/spf13/cobra" ) @@ -26,18 +27,20 @@ func init() { // Command to get a single OvhCloudConnect ovhcloudconnectCmd.AddCommand(&cobra.Command{ - Use: "get ", - Short: "Retrieve information of a specific OvhCloudConnect", - Args: cobra.ExactArgs(1), - Run: ovhcloudconnect.GetOvhCloudConnect, + Use: "get ", + Short: "Retrieve information of a specific OvhCloudConnect", + Args: cobra.ExactArgs(1), + ValidArgsFunction: completion.ServiceList("/v1/ovhCloudConnect"), + Run: ovhcloudconnect.GetOvhCloudConnect, }) // Command to update a single OvhCloudConnect ovhcloudconnectEditCmd := &cobra.Command{ - Use: "edit ", - Short: "Edit the given OvhCloudConnect", - Args: cobra.ExactArgs(1), - Run: ovhcloudconnect.EditOvhCloudConnect, + Use: "edit ", + Short: "Edit the given OvhCloudConnect", + Args: cobra.ExactArgs(1), + ValidArgsFunction: completion.ServiceList("/v1/ovhCloudConnect"), + Run: ovhcloudconnect.EditOvhCloudConnect, } ovhcloudconnectEditCmd.Flags().StringVar(&ovhcloudconnect.OvhCloudConnectSpec.Description, "description", "", "Description") addInteractiveEditorFlag(ovhcloudconnectEditCmd) diff --git a/internal/cmd/packxdsl.go b/internal/cmd/packxdsl.go index 95476821..f652c6b7 100644 --- a/internal/cmd/packxdsl.go +++ b/internal/cmd/packxdsl.go @@ -5,6 +5,7 @@ package cmd import ( + "github.com/ovh/ovhcloud-cli/internal/completion" "github.com/ovh/ovhcloud-cli/internal/services/packxdsl" "github.com/spf13/cobra" ) @@ -26,18 +27,20 @@ func init() { // Command to get a single PackXDSL packxdslCmd.AddCommand(&cobra.Command{ - Use: "get ", - Short: "Retrieve information of a specific PackXDSL", - Args: cobra.ExactArgs(1), - Run: packxdsl.GetPackXDSL, + Use: "get ", + Short: "Retrieve information of a specific PackXDSL", + Args: cobra.ExactArgs(1), + ValidArgsFunction: completion.ServiceList("/v1/pack/xdsl"), + Run: packxdsl.GetPackXDSL, }) // Command to update a single PackXDSL packxdslEditCmd := &cobra.Command{ - Use: "edit ", - Short: "Edit the given PackXDSL", - Args: cobra.ExactArgs(1), - Run: packxdsl.EditPackXDSL, + Use: "edit ", + Short: "Edit the given PackXDSL", + Args: cobra.ExactArgs(1), + ValidArgsFunction: completion.ServiceList("/v1/pack/xdsl"), + Run: packxdsl.EditPackXDSL, } packxdslEditCmd.Flags().StringVar(&packxdsl.PackXDSLSpec.Description, "description", "", "Description of the PackXDSL") addInteractiveEditorFlag(packxdslEditCmd) diff --git a/internal/cmd/root.go b/internal/cmd/root.go index 9e88d490..6116d2fc 100644 --- a/internal/cmd/root.go +++ b/internal/cmd/root.go @@ -129,9 +129,12 @@ Examples: var newVersionMessage atomic.Pointer[string] rootCmd.PersistentPreRun = func(cmd *cobra.Command, args []string) { // Skip authentication for the completion command and its subcommands - // (e.g. "ovhcloud completion bash") — no API access is needed. + // (e.g. "ovhcloud completion bash"), as well as the hidden commands cobra + // invokes for shell completion (pressing ) — no API access is needed, + // and failing here would make completion unusable when not authenticated. for c := cmd; c != nil; c = c.Parent() { - if c.Name() == "completion" { + switch c.Name() { + case "completion", cobra.ShellCompRequestCmd, cobra.ShellCompNoDescRequestCmd: return } } diff --git a/internal/cmd/sms.go b/internal/cmd/sms.go index 669ad665..d6221028 100644 --- a/internal/cmd/sms.go +++ b/internal/cmd/sms.go @@ -5,6 +5,7 @@ package cmd import ( + "github.com/ovh/ovhcloud-cli/internal/completion" "github.com/ovh/ovhcloud-cli/internal/services/sms" "github.com/spf13/cobra" ) @@ -26,18 +27,20 @@ func init() { // Command to get a single Sms smsCmd.AddCommand(&cobra.Command{ - Use: "get ", - Short: "Retrieve information of a specific SMS account", - Args: cobra.ExactArgs(1), - Run: sms.GetSms, + Use: "get ", + Short: "Retrieve information of a specific SMS account", + Args: cobra.ExactArgs(1), + ValidArgsFunction: completion.ServiceList("/v1/sms"), + Run: sms.GetSms, }) // Command to update a single Sms smsEditCmd := &cobra.Command{ - Use: "edit ", - Short: "Edit the given SMS account", - Args: cobra.ExactArgs(1), - Run: sms.EditSms, + Use: "edit ", + Short: "Edit the given SMS account", + Args: cobra.ExactArgs(1), + ValidArgsFunction: completion.ServiceList("/v1/sms"), + Run: sms.EditSms, } smsEditCmd.Flags().IntVar(&sms.SmsSpec.AutomaticRecreditAmount, "automatic-recredit-amount", 0, "Amount for automatic recredit (100, 200, 250, 500, 1000, 5000, 10000)") smsEditCmd.Flags().StringVar(&sms.SmsSpec.CallBack, "callback", "", "URL called when state of a sent SMS changes") diff --git a/internal/cmd/ssl.go b/internal/cmd/ssl.go index d1f218b3..1d66763c 100644 --- a/internal/cmd/ssl.go +++ b/internal/cmd/ssl.go @@ -5,6 +5,7 @@ package cmd import ( + "github.com/ovh/ovhcloud-cli/internal/completion" "github.com/ovh/ovhcloud-cli/internal/services/ssl" "github.com/spf13/cobra" ) @@ -26,10 +27,11 @@ func init() { // Command to get a single Ssl sslCmd.AddCommand(&cobra.Command{ - Use: "get ", - Short: "Retrieve information of a specific Ssl", - Args: cobra.ExactArgs(1), - Run: ssl.GetSsl, + Use: "get ", + Short: "Retrieve information of a specific Ssl", + Args: cobra.ExactArgs(1), + ValidArgsFunction: completion.ServiceList("/v1/ssl"), + Run: ssl.GetSsl, }) rootCmd.AddCommand(sslCmd) diff --git a/internal/cmd/sslgateway.go b/internal/cmd/sslgateway.go index 14af8bd3..44ef2c8d 100644 --- a/internal/cmd/sslgateway.go +++ b/internal/cmd/sslgateway.go @@ -5,6 +5,7 @@ package cmd import ( + "github.com/ovh/ovhcloud-cli/internal/completion" "github.com/ovh/ovhcloud-cli/internal/services/sslgateway" "github.com/spf13/cobra" ) @@ -26,18 +27,20 @@ func init() { // Command to get a single SslGateway sslgatewayCmd.AddCommand(&cobra.Command{ - Use: "get ", - Short: "Retrieve information of a specific SSL Gateway", - Args: cobra.ExactArgs(1), - Run: sslgateway.GetSslGateway, + Use: "get ", + Short: "Retrieve information of a specific SSL Gateway", + Args: cobra.ExactArgs(1), + ValidArgsFunction: completion.ServiceList("/v1/sslGateway"), + Run: sslgateway.GetSslGateway, }) // Command to update a single SslGateway sslgatewayEditCmd := &cobra.Command{ - Use: "edit ", - Short: "Edit the given SSL Gateway", - Args: cobra.ExactArgs(1), - Run: sslgateway.EditSslGateway, + Use: "edit ", + Short: "Edit the given SSL Gateway", + Args: cobra.ExactArgs(1), + ValidArgsFunction: completion.ServiceList("/v1/sslGateway"), + Run: sslgateway.EditSslGateway, } sslgatewayEditCmd.Flags().StringSliceVar(&sslgateway.SSLGatewaySpec.AllowedSource, "allowed-source", nil, "Restrict SSL Gateway access to these ip block") sslgatewayEditCmd.Flags().StringVar(&sslgateway.SSLGatewaySpec.DisplayName, "display-name", "", "Display name of the SSL Gateway") diff --git a/internal/cmd/storagenetapp.go b/internal/cmd/storagenetapp.go index 123fbee3..f1c85cb3 100644 --- a/internal/cmd/storagenetapp.go +++ b/internal/cmd/storagenetapp.go @@ -5,6 +5,7 @@ package cmd import ( + "github.com/ovh/ovhcloud-cli/internal/completion" "github.com/ovh/ovhcloud-cli/internal/services/storagenetapp" "github.com/spf13/cobra" ) @@ -26,18 +27,20 @@ func init() { // Command to get a single StorageNetApp storagenetappCmd.AddCommand(&cobra.Command{ - Use: "get ", - Short: "Retrieve information of a specific StorageNetApp", - Args: cobra.ExactArgs(1), - Run: storagenetapp.GetStorageNetApp, + Use: "get ", + Short: "Retrieve information of a specific StorageNetApp", + Args: cobra.ExactArgs(1), + ValidArgsFunction: completion.ServiceList("/v1/storage/netapp"), + Run: storagenetapp.GetStorageNetApp, }) // Command to update a single StorageNetApp storagenetappEditCmd := &cobra.Command{ - Use: "edit ", - Short: "Edit the given StorageNetApp", - Args: cobra.ExactArgs(1), - Run: storagenetapp.EditStorageNetApp, + Use: "edit ", + Short: "Edit the given StorageNetApp", + Args: cobra.ExactArgs(1), + ValidArgsFunction: completion.ServiceList("/v1/storage/netapp"), + Run: storagenetapp.EditStorageNetApp, } storagenetappEditCmd.Flags().StringVar(&storagenetapp.StorageNetAppSpec.Name, "name", "", "Name of the Storage NetApp") addInteractiveEditorFlag(storagenetappEditCmd) diff --git a/internal/cmd/supporttickets.go b/internal/cmd/supporttickets.go index 1aa62003..70f0c46c 100644 --- a/internal/cmd/supporttickets.go +++ b/internal/cmd/supporttickets.go @@ -6,6 +6,7 @@ package cmd import ( "github.com/ovh/ovhcloud-cli/internal/assets" + "github.com/ovh/ovhcloud-cli/internal/completion" "github.com/ovh/ovhcloud-cli/internal/services/supporttickets" "github.com/spf13/cobra" ) @@ -27,28 +28,31 @@ func init() { // Command to get a single support ticket supportticketsCmd.AddCommand(&cobra.Command{ - Use: "get ", - Short: "Retrieve information of a specific support ticket", - Args: cobra.ExactArgs(1), - Run: supporttickets.GetSupportTickets, + Use: "get ", + Short: "Retrieve information of a specific support ticket", + Args: cobra.ExactArgs(1), + ValidArgsFunction: completion.ServiceList("/v1/support/tickets"), + Run: supporttickets.GetSupportTickets, }) // Command to list messages for a support ticket supportticketsMessagesCmd := &cobra.Command{ - Use: "messages ", - Aliases: []string{"msgs"}, - Short: "List messages for a support ticket", - Args: cobra.ExactArgs(1), - Run: supporttickets.ListSupportTicketMessages, + Use: "messages ", + Aliases: []string{"msgs"}, + Short: "List messages for a support ticket", + Args: cobra.ExactArgs(1), + ValidArgsFunction: completion.ServiceList("/v1/support/tickets"), + Run: supporttickets.ListSupportTicketMessages, } supportticketsCmd.AddCommand(withFilterFlag(supportticketsMessagesCmd)) // Command to reply to a support ticket supportticketsReplyCmd := &cobra.Command{ - Use: "reply ", - Short: "Reply to a support ticket", - Args: cobra.ExactArgs(1), - Run: supporttickets.ReplySupportTicket, + Use: "reply ", + Short: "Reply to a support ticket", + Args: cobra.ExactArgs(1), + ValidArgsFunction: completion.ServiceList("/v1/support/tickets"), + Run: supporttickets.ReplySupportTicket, } supportticketsReplyCmd.Flags().StringVar(&supporttickets.ReplySpec.Body, "body", "", "Text body of the ticket reply") _ = supportticketsReplyCmd.MarkFlagRequired("body") diff --git a/internal/cmd/telephony.go b/internal/cmd/telephony.go index 34b7706a..eb13c5f4 100644 --- a/internal/cmd/telephony.go +++ b/internal/cmd/telephony.go @@ -5,6 +5,7 @@ package cmd import ( + "github.com/ovh/ovhcloud-cli/internal/completion" "github.com/ovh/ovhcloud-cli/internal/services/telephony" "github.com/spf13/cobra" ) @@ -26,18 +27,20 @@ func init() { // Command to get a single Telephony telephonyCmd.AddCommand(&cobra.Command{ - Use: "get ", - Short: "Retrieve information of a specific Telephony service", - Args: cobra.ExactArgs(1), - Run: telephony.GetTelephony, + Use: "get ", + Short: "Retrieve information of a specific Telephony service", + Args: cobra.ExactArgs(1), + ValidArgsFunction: completion.ServiceList("/v1/telephony"), + Run: telephony.GetTelephony, }) // Command to update a single Telephony telephonyEditCmd := &cobra.Command{ - Use: "edit ", - Short: "Edit the given Telephony service", - Args: cobra.ExactArgs(1), - Run: telephony.EditTelephony, + Use: "edit ", + Short: "Edit the given Telephony service", + Args: cobra.ExactArgs(1), + ValidArgsFunction: completion.ServiceList("/v1/telephony"), + Run: telephony.EditTelephony, } telephonyEditCmd.Flags().StringVar(&telephony.TelephonySpec.Description, "description", "", "Description of service") telephonyEditCmd.Flags().BoolVar(&telephony.TelephonySpec.HiddenExternalNumber, "hidden-external-number", false, "Hide called numbers in end-of-month call details CSV") diff --git a/internal/cmd/veeamcloudconnect.go b/internal/cmd/veeamcloudconnect.go index e35b9b83..c40336d6 100644 --- a/internal/cmd/veeamcloudconnect.go +++ b/internal/cmd/veeamcloudconnect.go @@ -5,6 +5,7 @@ package cmd import ( + "github.com/ovh/ovhcloud-cli/internal/completion" "github.com/ovh/ovhcloud-cli/internal/services/veeamcloudconnect" "github.com/spf13/cobra" ) @@ -26,10 +27,11 @@ func init() { // Command to get a single VeeamCloudConnect veeamcloudconnectCmd.AddCommand(&cobra.Command{ - Use: "get ", - Short: "Retrieve information of a specific VeeamCloudConnect", - Args: cobra.ExactArgs(1), - Run: veeamcloudconnect.GetVeeamCloudConnect, + Use: "get ", + Short: "Retrieve information of a specific VeeamCloudConnect", + Args: cobra.ExactArgs(1), + ValidArgsFunction: completion.ServiceList("/v1/veeamCloudConnect"), + Run: veeamcloudconnect.GetVeeamCloudConnect, }) rootCmd.AddCommand(veeamcloudconnectCmd) diff --git a/internal/cmd/veeamenterprise.go b/internal/cmd/veeamenterprise.go index c6a53957..590e2691 100644 --- a/internal/cmd/veeamenterprise.go +++ b/internal/cmd/veeamenterprise.go @@ -5,6 +5,7 @@ package cmd import ( + "github.com/ovh/ovhcloud-cli/internal/completion" "github.com/ovh/ovhcloud-cli/internal/services/veeamenterprise" "github.com/spf13/cobra" ) @@ -26,10 +27,11 @@ func init() { // Command to get a single VeeamEnterprise veeamenterpriseCmd.AddCommand(&cobra.Command{ - Use: "get ", - Short: "Retrieve information of a specific VeeamEnterprise", - Args: cobra.ExactArgs(1), - Run: veeamenterprise.GetVeeamEnterprise, + Use: "get ", + Short: "Retrieve information of a specific VeeamEnterprise", + Args: cobra.ExactArgs(1), + ValidArgsFunction: completion.ServiceList("/v1/veeam/veeamEnterprise"), + Run: veeamenterprise.GetVeeamEnterprise, }) rootCmd.AddCommand(veeamenterpriseCmd) diff --git a/internal/cmd/vmwareclouddirectorbackup.go b/internal/cmd/vmwareclouddirectorbackup.go index e78121a8..8fe9b3b2 100644 --- a/internal/cmd/vmwareclouddirectorbackup.go +++ b/internal/cmd/vmwareclouddirectorbackup.go @@ -5,6 +5,7 @@ package cmd import ( + "github.com/ovh/ovhcloud-cli/internal/completion" "github.com/ovh/ovhcloud-cli/internal/services/vmwareclouddirectorbackup" "github.com/spf13/cobra" ) @@ -26,18 +27,20 @@ func init() { // Command to get a single VmwareCloudDirectorBackup vmwareclouddirectorbackupCmd.AddCommand(&cobra.Command{ - Use: "get ", - Short: "Retrieve information of a specific VmwareCloudDirector Backup", - Args: cobra.ExactArgs(1), - Run: vmwareclouddirectorbackup.GetVmwareCloudDirectorBackup, + Use: "get ", + Short: "Retrieve information of a specific VmwareCloudDirector Backup", + Args: cobra.ExactArgs(1), + ValidArgsFunction: completion.ServiceList("/v2/vmwareCloudDirector/backup"), + Run: vmwareclouddirectorbackup.GetVmwareCloudDirectorBackup, }) // Command to update a single VmwareCloudDirectorBackup vmwareclouddirectorbackupEditCmd := &cobra.Command{ - Use: "edit ", - Short: "Edit the given VmwareCloudDirector Backup", - Args: cobra.ExactArgs(1), - Run: vmwareclouddirectorbackup.EditVmwareCloudDirectorBackup, + Use: "edit ", + Short: "Edit the given VmwareCloudDirector Backup", + Args: cobra.ExactArgs(1), + ValidArgsFunction: completion.ServiceList("/v2/vmwareCloudDirector/backup"), + Run: vmwareclouddirectorbackup.EditVmwareCloudDirectorBackup, } vmwareclouddirectorbackupEditCmd.Flags().StringSliceVar( &vmwareclouddirectorbackup.VmwareCloudDirectorBackupSpec.TargetSpec.CliOffers, diff --git a/internal/cmd/vmwareclouddirectororganization.go b/internal/cmd/vmwareclouddirectororganization.go index 9b79008b..b2311091 100644 --- a/internal/cmd/vmwareclouddirectororganization.go +++ b/internal/cmd/vmwareclouddirectororganization.go @@ -5,6 +5,7 @@ package cmd import ( + "github.com/ovh/ovhcloud-cli/internal/completion" "github.com/ovh/ovhcloud-cli/internal/services/vmwareclouddirectororganization" "github.com/spf13/cobra" ) @@ -26,18 +27,20 @@ func init() { // Command to get a single VmwareCloudDirector Organization vmwareclouddirectororganizationCmd.AddCommand(&cobra.Command{ - Use: "get ", - Short: "Retrieve information of a specific VmwareCloudDirector Organization", - Args: cobra.ExactArgs(1), - Run: vmwareclouddirectororganization.GetVmwareCloudDirectorOrganization, + Use: "get ", + Short: "Retrieve information of a specific VmwareCloudDirector Organization", + Args: cobra.ExactArgs(1), + ValidArgsFunction: completion.ServiceList("/v2/vmwareCloudDirector/organization"), + Run: vmwareclouddirectororganization.GetVmwareCloudDirectorOrganization, }) // Command to update a single VmwareCloudDirector Organization vmwareclouddirectororganizationEditCmd := &cobra.Command{ - Use: "edit ", - Short: "Edit the given VmwareCloudDirector Organization", - Args: cobra.ExactArgs(1), - Run: vmwareclouddirectororganization.EditVmwareCloudDirectorOrganization, + Use: "edit ", + Short: "Edit the given VmwareCloudDirector Organization", + Args: cobra.ExactArgs(1), + ValidArgsFunction: completion.ServiceList("/v2/vmwareCloudDirector/organization"), + Run: vmwareclouddirectororganization.EditVmwareCloudDirectorOrganization, } vmwareclouddirectororganizationEditCmd.Flags().StringVar(&vmwareclouddirectororganization.VmwareCloudDirectorOrganizationSpec.TargetSpec.Description, "description", "", "Description of the organization") vmwareclouddirectororganizationEditCmd.Flags().StringVar(&vmwareclouddirectororganization.VmwareCloudDirectorOrganizationSpec.TargetSpec.FullName, "full-name", "", "Full name of the organization") diff --git a/internal/cmd/vps.go b/internal/cmd/vps.go index 4e6ad299..acb2ea78 100644 --- a/internal/cmd/vps.go +++ b/internal/cmd/vps.go @@ -9,6 +9,7 @@ import ( "runtime" "github.com/ovh/ovhcloud-cli/internal/assets" + "github.com/ovh/ovhcloud-cli/internal/completion" "github.com/ovh/ovhcloud-cli/internal/flags" "github.com/ovh/ovhcloud-cli/internal/services/common" "github.com/ovh/ovhcloud-cli/internal/services/vps" @@ -32,18 +33,20 @@ func init() { // Command to get a single VPS vpsCmd.AddCommand(&cobra.Command{ - Use: "get ", - Short: "Retrieve information of a specific VPS", - Args: cobra.ExactArgs(1), - Run: vps.GetVps, + Use: "get ", + Short: "Retrieve information of a specific VPS", + Args: cobra.ExactArgs(1), + ValidArgsFunction: completion.ServiceList("/v1/vps"), + Run: vps.GetVps, }) // Command to update a single VPS vpsEditCmd := &cobra.Command{ - Use: "edit ", - Short: "Edit the given VPS", - Args: cobra.ExactArgs(1), - Run: vps.EditVps, + Use: "edit ", + Short: "Edit the given VPS", + Args: cobra.ExactArgs(1), + ValidArgsFunction: completion.ServiceList("/v1/vps"), + Run: vps.EditVps, } vpsEditCmd.Flags().StringVar(&vps.VpsSpec.DisplayName, "display-name", "", "Display name of the VPS") vpsEditCmd.Flags().StringVar(&vps.VpsSpec.Keymap, "keymap", "", "Keymap of the VPS (fr, us)") @@ -60,57 +63,64 @@ func init() { vpsCmd.AddCommand(vpsSnapshotCmd) vpsSnapshotCmd.AddCommand(&cobra.Command{ - Use: "get ", - Short: "Retrieve information of a specific VPS snapshot", - Args: cobra.ExactArgs(1), - Run: vps.GetVpsSnapshot, + Use: "get ", + Short: "Retrieve information of a specific VPS snapshot", + Args: cobra.ExactArgs(1), + ValidArgsFunction: completion.ServiceList("/v1/vps"), + Run: vps.GetVpsSnapshot, }) vpsSnapshotCreateCmd := &cobra.Command{ - Use: "create ", - Short: "Create a snapshot of the given VPS", - Args: cobra.ExactArgs(1), - Run: vps.CreateVpsSnapshot, + Use: "create ", + Short: "Create a snapshot of the given VPS", + Args: cobra.ExactArgs(1), + ValidArgsFunction: completion.ServiceList("/v1/vps"), + Run: vps.CreateVpsSnapshot, } vpsSnapshotCreateCmd.Flags().StringVar(&vps.VpsSnapshotSpec.Description, "description", "", "Description of the snapshot") vpsSnapshotCmd.AddCommand(vpsSnapshotCreateCmd) vpsSnapshotEditCmd := &cobra.Command{ - Use: "edit ", - Short: "Edit the given VPS snapshot", - Args: cobra.ExactArgs(1), - Run: vps.EditVpsSnapshot, + Use: "edit ", + Short: "Edit the given VPS snapshot", + Args: cobra.ExactArgs(1), + ValidArgsFunction: completion.ServiceList("/v1/vps"), + Run: vps.EditVpsSnapshot, } vpsSnapshotEditCmd.Flags().StringVar(&vps.VpsSnapshotSpec.Description, "description", "", "Description of the snapshot") addInteractiveEditorFlag(vpsSnapshotEditCmd) vpsSnapshotCmd.AddCommand(vpsSnapshotEditCmd) vpsSnapshotCmd.AddCommand(&cobra.Command{ - Use: "delete ", - Short: "Delete the given VPS snapshot", - Args: cobra.ExactArgs(1), - Run: vps.DeleteVpsSnapshot, + Use: "delete ", + Short: "Delete the given VPS snapshot", + Args: cobra.ExactArgs(1), + ValidArgsFunction: completion.ServiceList("/v1/vps"), + Run: vps.DeleteVpsSnapshot, }) vpsSnapshotCmd.AddCommand(&cobra.Command{ - Use: "abort ", - Short: "Abort the creation of a VPS snapshot", - Args: cobra.ExactArgs(1), - Run: vps.AbortVpsSnapshot, + Use: "abort ", + Short: "Abort the creation of a VPS snapshot", + Args: cobra.ExactArgs(1), + ValidArgsFunction: completion.ServiceList("/v1/vps"), + Run: vps.AbortVpsSnapshot, }) vpsSnapshotCmd.AddCommand(&cobra.Command{ - Use: "restore ", - Short: "Restore the snapshot of the given VPS", - Args: cobra.ExactArgs(1), - Run: vps.RestoreVpsSnapshot, + Use: "restore ", + Short: "Restore the snapshot of the given VPS", + Args: cobra.ExactArgs(1), + ValidArgsFunction: completion.ServiceList("/v1/vps"), + Run: vps.RestoreVpsSnapshot, }) vpsSnapshotCmd.AddCommand(&cobra.Command{ - Use: "download ", - Short: "Download the snapshot of the given VPS", - Args: cobra.ExactArgs(1), - Run: vps.DownloadVpsSnapshot, + Use: "download ", + Short: "Download the snapshot of the given VPS", + Args: cobra.ExactArgs(1), + ValidArgsFunction: completion.ServiceList("/v1/vps"), + Run: vps.DownloadVpsSnapshot, }) // Automated backup commands @@ -121,33 +131,37 @@ func init() { vpsCmd.AddCommand(vpsBackupCmd) vpsBackupCmd.AddCommand(&cobra.Command{ - Use: "get-config ", - Short: "Retrieve automated backup configuration of the given VPS", - Args: cobra.ExactArgs(1), - Run: vps.GetVpsAutomatedBackup, + Use: "get-config ", + Short: "Retrieve automated backup configuration of the given VPS", + Args: cobra.ExactArgs(1), + ValidArgsFunction: completion.ServiceList("/v1/vps"), + Run: vps.GetVpsAutomatedBackup, }) vpsBackupCmd.AddCommand(withFilterFlag(&cobra.Command{ - Use: "list ", - Aliases: []string{"ls"}, - Short: "List all automated backups of the given VPS", - Args: cobra.ExactArgs(1), - Run: vps.ListVpsAutomatedBackups, + Use: "list ", + Aliases: []string{"ls"}, + Short: "List all automated backups of the given VPS", + Args: cobra.ExactArgs(1), + ValidArgsFunction: completion.ServiceList("/v1/vps"), + Run: vps.ListVpsAutomatedBackups, })) vpsBackupCmd.AddCommand(&cobra.Command{ - Use: "reschedule