From 5db50500a1cfd9fc78a54303e45f498a8dae9c87 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julian=20T=C3=B6lle?= Date: Mon, 28 Nov 2022 14:28:03 +0100 Subject: [PATCH] feat(completion): read network zones from API We previously hard-coded the available network zones for autocompletion purposes. This makes it easy to forget to add them, or only update the list in one location (as you can see, it's currently missing us-east for the loadbalancer create call). In this PR we replace the hardcoded list with an api call that retrieves all available network zones from the API. As there is no dedicated `GET /v1/network_zones` endpoint, we use the network zone referenced in the `GET /v1/locations` response. --- internal/cmd/loadbalancer/create.go | 2 +- internal/cmd/network/add_subnet.go | 2 +- internal/hcapi/location.go | 23 +++++++++++++++++++++++ internal/state/helpers.go | 8 ++++++++ 4 files changed, 33 insertions(+), 2 deletions(-) diff --git a/internal/cmd/loadbalancer/create.go b/internal/cmd/loadbalancer/create.go index 8914edfb..99b8b5ee 100644 --- a/internal/cmd/loadbalancer/create.go +++ b/internal/cmd/loadbalancer/create.go @@ -36,7 +36,7 @@ func newCreateCommand(cli *state.State) *cobra.Command { cmd.RegisterFlagCompletionFunc("location", cmpl.SuggestCandidatesF(cli.LocationNames)) cmd.Flags().String("network-zone", "", "Network Zone") - cmd.RegisterFlagCompletionFunc("network-zone", cmpl.SuggestCandidates("eu-central")) + cmd.RegisterFlagCompletionFunc("network-zone", cmpl.SuggestCandidatesF(cli.NetworkZoneNames)) cmd.Flags().StringToString("label", nil, "User-defined labels ('key=value') (can be specified multiple times)") diff --git a/internal/cmd/network/add_subnet.go b/internal/cmd/network/add_subnet.go index 6eab3108..d02b2714 100644 --- a/internal/cmd/network/add_subnet.go +++ b/internal/cmd/network/add_subnet.go @@ -27,7 +27,7 @@ func newAddSubnetCommand(cli *state.State) *cobra.Command { cmd.MarkFlagRequired("type") cmd.Flags().String("network-zone", "", "Name of network zone (required)") - cmd.RegisterFlagCompletionFunc("network-zone", cmpl.SuggestCandidates("eu-central", "us-east")) + cmd.RegisterFlagCompletionFunc("network-zone", cmpl.SuggestCandidatesF(cli.NetworkZoneNames)) cmd.MarkFlagRequired("network-zone") cmd.Flags().IPNet("ip-range", net.IPNet{}, "Range to allocate IPs from") diff --git a/internal/hcapi/location.go b/internal/hcapi/location.go index f76aa973..aab63cdb 100644 --- a/internal/hcapi/location.go +++ b/internal/hcapi/location.go @@ -30,3 +30,26 @@ func (c *LocationClient) LocationNames() []string { } return names } + +// NetworkZoneNames obtains a list of available network zones. It returns nil if +// network zone names could not be fetched. +func (c *LocationClient) NetworkZoneNames() []string { + locs, err := c.All(context.Background()) + if err != nil || len(locs) == 0 { + return nil + } + // Use map to get unique elements + namesMap := map[hcloud.NetworkZone]bool{} + for _, loc := range locs { + name := loc.NetworkZone + namesMap[name] = true + } + + // Unique names from map to slice + names := make([]string, len(namesMap)) + for name := range namesMap { + names = append(names, string(name)) + } + + return names +} diff --git a/internal/state/helpers.go b/internal/state/helpers.go index 6c2e709d..721bac89 100644 --- a/internal/state/helpers.go +++ b/internal/state/helpers.go @@ -143,6 +143,14 @@ func (c *State) LocationNames() []string { return c.locationClient.LocationNames() } +func (c *State) NetworkZoneNames() []string { + if c.locationClient == nil { + client := c.Client() + c.locationClient = &hcapi.LocationClient{LocationClient: &client.Location} + } + return c.locationClient.NetworkZoneNames() +} + func (c *State) DataCenterNames() []string { if c.dataCenterClient == nil { client := c.Client()