diff --git a/lxc/completion.go b/lxc/completion.go index d115eba5c9bb..65a5ade7f859 100644 --- a/lxc/completion.go +++ b/lxc/completion.go @@ -211,6 +211,18 @@ func (g *cmdGlobal) cmpImages(toComplete string) ([]string, cobra.ShellCompDirec } func (g *cmdGlobal) cmpInstanceAllKeys(instanceName string) ([]string, cobra.ShellCompDirective) { + var keys []string + cmpDirectives := cobra.ShellCompDirectiveNoFileComp + + _, instanceNameOnly, _ := strings.Cut(instanceName, ":") + if instanceNameOnly == "" { + serverKeys, directives := g.cmpServerAllKeys(instanceName) + keys = append(keys, serverKeys...) + cmpDirectives = directives + + return keys, cmpDirectives + } + resources, err := g.ParseServers(instanceName) if err != nil || len(resources) == 0 { return nil, cobra.ShellCompDirectiveError @@ -219,13 +231,12 @@ func (g *cmdGlobal) cmpInstanceAllKeys(instanceName string) ([]string, cobra.She resource := resources[0] client := resource.server - instanceNameOnly, _, err := client.GetInstance(instanceName) + instance, _, err := client.GetInstance(instanceNameOnly) if err != nil { return nil, cobra.ShellCompDirectiveError } - var keys []string - instanceType := instanceNameOnly.Type + instanceType := instance.Type if instanceType == "container" { for k := range instancetype.InstanceConfigKeysContainer { @@ -241,6 +252,63 @@ func (g *cmdGlobal) cmpInstanceAllKeys(instanceName string) ([]string, cobra.She keys = append(keys, k) } + return keys, cmpDirectives +} + +func (g *cmdGlobal) cmpServerAllKeys(instanceName string) ([]string, cobra.ShellCompDirective) { + var keys []string + + resources, err := g.ParseServers(instanceName) + if err != nil || len(resources) == 0 { + return nil, cobra.ShellCompDirectiveError + } + + resource := resources[0] + client := resource.server + + config, err := client.GetMetadataConfiguration() + if err != nil { + return nil, cobra.ShellCompDirectiveError + } + + metadata, ok := (*config)["metadata"].(map[string]any) + if !ok { + return nil, cobra.ShellCompDirectiveError + } + + configs, ok := metadata["configs"].(map[string]any) + if !ok { + return nil, cobra.ShellCompDirectiveError + } + + server, ok := configs["server"].(map[string]any) + if !ok { + return nil, cobra.ShellCompDirectiveError + } + + for _, field := range server { + fieldMap, ok := field.(map[string]any) + if !ok { + return nil, cobra.ShellCompDirectiveError + } + + keyArray, ok := fieldMap["keys"].([]any) + if !ok { + return nil, cobra.ShellCompDirectiveError + } + + for _, keyObj := range keyArray { + keyMap, ok := keyObj.(map[string]any) + if !ok { + return nil, cobra.ShellCompDirectiveError + } + + for k := range keyMap { + keys = append(keys, k) + } + } + } + return keys, cobra.ShellCompDirectiveNoFileComp } @@ -937,6 +1005,10 @@ func (g *cmdGlobal) cmpRemotes(includeAll bool) ([]string, cobra.ShellCompDirect continue } + if remoteName == "local" || rc.Protocol == "simplestreams" { + continue + } + results = append(results, fmt.Sprintf("%s:", remoteName)) } diff --git a/lxc/config.go b/lxc/config.go index 837c1a3616e8..3c22c89c9569 100644 --- a/lxc/config.go +++ b/lxc/config.go @@ -400,6 +400,10 @@ func (c *cmdConfigGet) command() *cobra.Command { cmd.ValidArgsFunction = func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { if len(args) == 0 { + if strings.Contains(toComplete, ".") { + return c.global.cmpServerAllKeys(toComplete) + } + return c.global.cmpInstances(toComplete) } @@ -553,6 +557,10 @@ lxc config set core.https_address=[::]:8443 cmd.ValidArgsFunction = func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { if len(args) == 0 { + if strings.Contains(toComplete, ".") { + return c.global.cmpServerAllKeys(toComplete) + } + return c.global.cmpInstances(toComplete) } @@ -902,6 +910,10 @@ func (c *cmdConfigUnset) command() *cobra.Command { cmd.ValidArgsFunction = func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { if len(args) == 0 { + if strings.Contains(toComplete, ".") { + return c.global.cmpServerAllKeys(toComplete) + } + return c.global.cmpInstances(toComplete) }