Skip to content

Commit

Permalink
refactor: split up label command into separate Fetch/GetLabels/GetIDO…
Browse files Browse the repository at this point in the history
…rName
  • Loading branch information
phm07 committed Jan 23, 2025
1 parent 48b4fc7 commit 4ea8a26
Show file tree
Hide file tree
Showing 23 changed files with 307 additions and 166 deletions.
28 changes: 17 additions & 11 deletions internal/cmd/base/labels.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,10 @@ type LabelCmds struct {
ShortDescriptionRemove string
NameSuggestions func(client hcapi2.Client) func() []string
LabelKeySuggestions func(client hcapi2.Client) func(idOrName string) []string
FetchLabels func(s state.State, idOrName string) (map[string]string, int64, error)
SetLabels func(s state.State, id int64, labels map[string]string) error
Fetch func(s state.State, idOrName string) (any, error)
SetLabels func(s state.State, resource any, labels map[string]string) error
GetLabels func(resource any) map[string]string
GetIDOrName func(resource any) string
}

// AddCobraCommand creates a command that can be registered with cobra.
Expand All @@ -47,11 +49,13 @@ func (lc *LabelCmds) RunAdd(s state.State, cmd *cobra.Command, args []string) er
overwrite, _ := cmd.Flags().GetBool("overwrite")
idOrName := args[0]

labels, id, err := lc.FetchLabels(s, idOrName)
resource, err := lc.Fetch(s, idOrName)
if err != nil {
return err
}

labels, idOrName := lc.GetLabels(resource), lc.GetIDOrName(resource)

if labels == nil {
labels = map[string]string{}
}
Expand All @@ -62,17 +66,17 @@ func (lc *LabelCmds) RunAdd(s state.State, cmd *cobra.Command, args []string) er
keys = append(keys, key)

if _, ok := labels[key]; ok && !overwrite {
return fmt.Errorf("label %s on %s %d already exists", key, lc.ResourceNameSingular, id)
return fmt.Errorf("label %s on %s %s already exists", key, lc.ResourceNameSingular, idOrName)
}

labels[key] = val
}

if err := lc.SetLabels(s, id, labels); err != nil {
if err := lc.SetLabels(s, resource, labels); err != nil {
return err
}

cmd.Printf("Label(s) %s added to %s %d\n", strings.Join(keys, ", "), lc.ResourceNameSingular, id)
cmd.Printf("Label(s) %s added to %s %s\n", strings.Join(keys, ", "), lc.ResourceNameSingular, idOrName)
return nil
}

Expand Down Expand Up @@ -117,30 +121,32 @@ func (lc *LabelCmds) RunRemove(s state.State, cmd *cobra.Command, args []string)
all, _ := cmd.Flags().GetBool("all")
idOrName := args[0]

labels, id, err := lc.FetchLabels(s, idOrName)
resource, err := lc.Fetch(s, idOrName)
if err != nil {
return err
}

labels, idOrName := lc.GetLabels(resource), lc.GetIDOrName(resource)

if all {
labels = make(map[string]string)
} else {
for _, key := range args[1:] {
if _, ok := labels[key]; !ok {
return fmt.Errorf("label %s on %s %d does not exist", key, lc.ResourceNameSingular, id)
return fmt.Errorf("label %s on %s %s does not exist", key, lc.ResourceNameSingular, idOrName)
}
delete(labels, key)
}
}

if err := lc.SetLabels(s, id, labels); err != nil {
if err := lc.SetLabels(s, resource, labels); err != nil {
return err
}

if all {
cmd.Printf("All labels removed from %s %d\n", lc.ResourceNameSingular, id)
cmd.Printf("All labels removed from %s %s\n", lc.ResourceNameSingular, idOrName)
} else {
cmd.Printf("Label(s) %s removed from %s %d\n", strings.Join(args[1:], ", "), lc.ResourceNameSingular, id)
cmd.Printf("Label(s) %s removed from %s %s\n", strings.Join(args[1:], ", "), lc.ResourceNameSingular, idOrName)
}

return nil
Expand Down
22 changes: 16 additions & 6 deletions internal/cmd/certificate/labels.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package certificate

import (
"fmt"
"strconv"

"github.com/hetznercloud/cli/internal/cmd/base"
"github.com/hetznercloud/cli/internal/hcapi2"
Expand All @@ -15,21 +16,30 @@ var LabelCmds = base.LabelCmds{
ShortDescriptionRemove: "Remove a label from an certificate",
NameSuggestions: func(c hcapi2.Client) func() []string { return c.Certificate().Names },
LabelKeySuggestions: func(c hcapi2.Client) func(idOrName string) []string { return c.Certificate().LabelKeys },
FetchLabels: func(s state.State, idOrName string) (map[string]string, int64, error) {
Fetch: func(s state.State, idOrName string) (any, error) {
certificate, _, err := s.Client().Certificate().Get(s, idOrName)
if err != nil {
return nil, 0, err
return nil, err
}
if certificate == nil {
return nil, 0, fmt.Errorf("certificate not found: %s", idOrName)
return nil, fmt.Errorf("certificate not found: %s", idOrName)
}
return certificate.Labels, certificate.ID, nil
return certificate, nil
},
SetLabels: func(s state.State, id int64, labels map[string]string) error {
SetLabels: func(s state.State, resource any, labels map[string]string) error {
cert := resource.(*hcloud.Certificate)
opts := hcloud.CertificateUpdateOpts{
Labels: labels,
}
_, _, err := s.Client().Certificate().Update(s, &hcloud.Certificate{ID: id}, opts)
_, _, err := s.Client().Certificate().Update(s, cert, opts)
return err
},
GetLabels: func(resource any) map[string]string {
cert := resource.(*hcloud.Certificate)
return cert.Labels
},
GetIDOrName: func(resource any) string {
cert := resource.(*hcloud.Certificate)
return strconv.FormatInt(cert.ID, 10)
},
}
16 changes: 9 additions & 7 deletions internal/cmd/certificate/labels_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,16 +45,18 @@ func TestLabelRemove(t *testing.T) {
cmd := certificate.LabelCmds.RemoveCobraCommand(fx.State())
fx.ExpectEnsureToken()

cert := &hcloud.Certificate{
ID: 123,
Labels: map[string]string{
"key": "value",
},
}

fx.Client.CertificateClient.EXPECT().
Get(gomock.Any(), "123").
Return(&hcloud.Certificate{
ID: 123,
Labels: map[string]string{
"key": "value",
},
}, nil, nil)
Return(cert, nil, nil)
fx.Client.CertificateClient.EXPECT().
Update(gomock.Any(), &hcloud.Certificate{ID: 123}, hcloud.CertificateUpdateOpts{
Update(gomock.Any(), cert, hcloud.CertificateUpdateOpts{
Labels: make(map[string]string),
})

Expand Down
22 changes: 16 additions & 6 deletions internal/cmd/firewall/labels.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package firewall

import (
"fmt"
"strconv"

"github.com/hetznercloud/cli/internal/cmd/base"
"github.com/hetznercloud/cli/internal/hcapi2"
Expand All @@ -15,21 +16,30 @@ var LabelCmds = base.LabelCmds{
ShortDescriptionRemove: "Remove a label from an firewall",
NameSuggestions: func(c hcapi2.Client) func() []string { return c.Firewall().Names },
LabelKeySuggestions: func(c hcapi2.Client) func(idOrName string) []string { return c.Firewall().LabelKeys },
FetchLabels: func(s state.State, idOrName string) (map[string]string, int64, error) {
Fetch: func(s state.State, idOrName string) (any, error) {
firewall, _, err := s.Client().Firewall().Get(s, idOrName)
if err != nil {
return nil, 0, err
return nil, err
}
if firewall == nil {
return nil, 0, fmt.Errorf("firewall not found: %s", idOrName)
return nil, fmt.Errorf("firewall not found: %s", idOrName)
}
return firewall.Labels, firewall.ID, nil
return firewall, nil
},
SetLabels: func(s state.State, id int64, labels map[string]string) error {
SetLabels: func(s state.State, resource any, labels map[string]string) error {
firewall := resource.(*hcloud.Firewall)
opts := hcloud.FirewallUpdateOpts{
Labels: labels,
}
_, _, err := s.Client().Firewall().Update(s, &hcloud.Firewall{ID: id}, opts)
_, _, err := s.Client().Firewall().Update(s, firewall, opts)
return err
},
GetLabels: func(resource any) map[string]string {
firewall := resource.(*hcloud.Firewall)
return firewall.Labels
},
GetIDOrName: func(resource any) string {
firewall := resource.(*hcloud.Firewall)
return strconv.FormatInt(firewall.ID, 10)
},
}
16 changes: 9 additions & 7 deletions internal/cmd/firewall/labels_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,16 +45,18 @@ func TestLabelRemove(t *testing.T) {
cmd := firewall.LabelCmds.RemoveCobraCommand(fx.State())
fx.ExpectEnsureToken()

fw := &hcloud.Firewall{
ID: 123,
Labels: map[string]string{
"key": "value",
},
}

fx.Client.FirewallClient.EXPECT().
Get(gomock.Any(), "123").
Return(&hcloud.Firewall{
ID: 123,
Labels: map[string]string{
"key": "value",
},
}, nil, nil)
Return(fw, nil, nil)
fx.Client.FirewallClient.EXPECT().
Update(gomock.Any(), &hcloud.Firewall{ID: 123}, hcloud.FirewallUpdateOpts{
Update(gomock.Any(), fw, hcloud.FirewallUpdateOpts{
Labels: make(map[string]string),
})

Expand Down
22 changes: 16 additions & 6 deletions internal/cmd/floatingip/labels.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package floatingip

import (
"fmt"
"strconv"

"github.com/hetznercloud/cli/internal/cmd/base"
"github.com/hetznercloud/cli/internal/hcapi2"
Expand All @@ -15,21 +16,30 @@ var LabelCmds = base.LabelCmds{
ShortDescriptionRemove: "Remove a label from an Floating IP",
NameSuggestions: func(c hcapi2.Client) func() []string { return c.FloatingIP().Names },
LabelKeySuggestions: func(c hcapi2.Client) func(idOrName string) []string { return c.FloatingIP().LabelKeys },
FetchLabels: func(s state.State, idOrName string) (map[string]string, int64, error) {
Fetch: func(s state.State, idOrName string) (any, error) {
floatingIP, _, err := s.Client().FloatingIP().Get(s, idOrName)
if err != nil {
return nil, 0, err
return nil, err
}
if floatingIP == nil {
return nil, 0, fmt.Errorf("floating IP not found: %s", idOrName)
return nil, fmt.Errorf("floating IP not found: %s", idOrName)
}
return floatingIP.Labels, floatingIP.ID, nil
return floatingIP, nil
},
SetLabels: func(s state.State, id int64, labels map[string]string) error {
SetLabels: func(s state.State, resource any, labels map[string]string) error {
floatingIP := resource.(*hcloud.FloatingIP)
opts := hcloud.FloatingIPUpdateOpts{
Labels: labels,
}
_, _, err := s.Client().FloatingIP().Update(s, &hcloud.FloatingIP{ID: id}, opts)
_, _, err := s.Client().FloatingIP().Update(s, floatingIP, opts)
return err
},
GetLabels: func(resource any) map[string]string {
floatingIP := resource.(*hcloud.FloatingIP)
return floatingIP.Labels
},
GetIDOrName: func(resource any) string {
floatingIP := resource.(*hcloud.FloatingIP)
return strconv.FormatInt(floatingIP.ID, 10)
},
}
16 changes: 9 additions & 7 deletions internal/cmd/floatingip/labels_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,16 +45,18 @@ func TestLabelRemove(t *testing.T) {
cmd := floatingip.LabelCmds.RemoveCobraCommand(fx.State())
fx.ExpectEnsureToken()

floatingIP := &hcloud.FloatingIP{
ID: 123,
Labels: map[string]string{
"key": "value",
},
}

fx.Client.FloatingIPClient.EXPECT().
Get(gomock.Any(), "123").
Return(&hcloud.FloatingIP{
ID: 123,
Labels: map[string]string{
"key": "value",
},
}, nil, nil)
Return(floatingIP, nil, nil)
fx.Client.FloatingIPClient.EXPECT().
Update(gomock.Any(), &hcloud.FloatingIP{ID: 123}, hcloud.FloatingIPUpdateOpts{
Update(gomock.Any(), floatingIP, hcloud.FloatingIPUpdateOpts{
Labels: make(map[string]string),
})

Expand Down
23 changes: 16 additions & 7 deletions internal/cmd/image/labels.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,25 +16,34 @@ var LabelCmds = base.LabelCmds{
ShortDescriptionRemove: "Remove a label from an image",
NameSuggestions: func(c hcapi2.Client) func() []string { return c.Image().Names },
LabelKeySuggestions: func(c hcapi2.Client) func(idOrName string) []string { return c.Image().LabelKeys },
FetchLabels: func(s state.State, idOrName string) (map[string]string, int64, error) {
Fetch: func(s state.State, idOrName string) (any, error) {
id, err := strconv.ParseInt(idOrName, 10, 64)
if err != nil {
return nil, 0, fmt.Errorf("invalid snapshot or backup ID %q", idOrName)
return nil, fmt.Errorf("invalid snapshot or backup ID %q", idOrName)
}
image, _, err := s.Client().Image().GetByID(s, id)
if err != nil {
return nil, 0, err
return nil, err
}
if image == nil {
return nil, 0, fmt.Errorf("image not found: %s", idOrName)
return nil, fmt.Errorf("image not found: %s", idOrName)
}
return image.Labels, image.ID, nil
return image, nil
},
SetLabels: func(s state.State, id int64, labels map[string]string) error {
SetLabels: func(s state.State, resource any, labels map[string]string) error {
image := resource.(*hcloud.Image)
opts := hcloud.ImageUpdateOpts{
Labels: labels,
}
_, _, err := s.Client().Image().Update(s, &hcloud.Image{ID: id}, opts)
_, _, err := s.Client().Image().Update(s, image, opts)
return err
},
GetLabels: func(resource any) map[string]string {
image := resource.(*hcloud.Image)
return image.Labels
},
GetIDOrName: func(resource any) string {
image := resource.(*hcloud.Image)
return strconv.FormatInt(image.ID, 10)
},
}
16 changes: 9 additions & 7 deletions internal/cmd/image/labels_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,16 +45,18 @@ func TestLabelRemove(t *testing.T) {
cmd := image.LabelCmds.RemoveCobraCommand(fx.State())
fx.ExpectEnsureToken()

img := &hcloud.Image{
ID: 123,
Labels: map[string]string{
"key": "value",
},
}

fx.Client.ImageClient.EXPECT().
GetByID(gomock.Any(), int64(123)).
Return(&hcloud.Image{
ID: 123,
Labels: map[string]string{
"key": "value",
},
}, nil, nil)
Return(img, nil, nil)
fx.Client.ImageClient.EXPECT().
Update(gomock.Any(), &hcloud.Image{ID: 123}, hcloud.ImageUpdateOpts{
Update(gomock.Any(), img, hcloud.ImageUpdateOpts{
Labels: make(map[string]string),
})

Expand Down
Loading

0 comments on commit 4ea8a26

Please sign in to comment.