From 63e2d120b78254b8d64a76bac3c95e4804e7be48 Mon Sep 17 00:00:00 2001 From: Kadin Sayani Date: Tue, 26 Nov 2024 13:36:54 -0700 Subject: [PATCH] lxc/completion: Add `cmpInstanceSetKeys` function This commit adds a completion function for completing config keys which are currently set. Signed-off-by: Kadin Sayani --- lxc/completion.go | 47 +++++++++++++++++++++++++++++++++++++++++++++++ lxc/config.go | 3 ++- 2 files changed, 49 insertions(+), 1 deletion(-) diff --git a/lxc/completion.go b/lxc/completion.go index 0bba8eecab0e..1ca9ff9bdecb 100644 --- a/lxc/completion.go +++ b/lxc/completion.go @@ -336,6 +336,53 @@ func (g *cmdGlobal) cmpInstanceAllKeys(profileName string) ([]string, cobra.Shel return configKeys, cmpDirectives | cobra.ShellCompDirectiveNoSpace } +// cmpInstanceSetKeys provides shell completion for instance configuration keys which are currently set. +// It takes an instance name to determine instance type and returns a list of instance configuration keys along with a shell completion directive. +func (g *cmdGlobal) cmpInstanceSetKeys(instanceName string) ([]string, cobra.ShellCompDirective) { + cmpDirectives := cobra.ShellCompDirectiveNoFileComp + + // Early return when completing server keys. + _, instanceNameOnly, found := strings.Cut(instanceName, ":") + if instanceNameOnly == "" && found { + return g.cmpServerAllKeys(instanceName) + } + + resources, err := g.ParseServers(instanceName) + if err != nil || len(resources) == 0 { + return nil, cobra.ShellCompDirectiveError + } + + resource := resources[0] + client := resource.server + + instance, _, err := client.GetInstance(instanceName) + if err != nil { + return nil, cobra.ShellCompDirectiveError + } + + // Pre-allocate configKeys slice capacity. + keyCount := len(instance.Config) + + // Fetch all config keys that can be set by a user. + allInstanceConfigKeys, _ := g.cmpInstanceAllKeys(instanceName) + + // Convert slice to map[string]struct{} for O(1) lookups. + keySet := make(map[string]struct{}, len(allInstanceConfigKeys)) + for _, key := range allInstanceConfigKeys { + keySet[key] = struct{}{} + } + + configKeys := make([]string, 0, keyCount) + for configKey := range instance.Config { + // We only want to return the intersection between allInstanceConfigKeys and configKeys to avoid returning the full instance config. + if _, exists := keySet[configKey]; exists { + configKeys = append(configKeys, configKey) + } + } + + return configKeys, cmpDirectives | cobra.ShellCompDirectiveNoSpace +} + // cmpServerAllKeys provides shell completion for all server configuration keys. // It takes an instance name and returns a list of all server configuration keys along with a shell completion directive. func (g *cmdGlobal) cmpServerAllKeys(instanceName string) ([]string, cobra.ShellCompDirective) { diff --git a/lxc/config.go b/lxc/config.go index 6c4efa629f4a..f4f522c43233 100644 --- a/lxc/config.go +++ b/lxc/config.go @@ -918,7 +918,8 @@ func (c *cmdConfigUnset) command() *cobra.Command { } if len(args) == 1 { - return c.global.cmpInstanceKeys(args[0]) + // Only complete config keys which are currently set. + return c.global.cmpInstanceSetKeys(args[0]) } return nil, cobra.ShellCompDirectiveNoFileComp