Skip to content

Commit bf79862

Browse files
authored
Add support for labels (#126)
Co-authored-by: Thomas Cyron <thomas@thcyron.de>
1 parent 84e2bb2 commit bf79862

41 files changed

Lines changed: 1218 additions & 76 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

CHANGES.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
## master
44

55
* Add type filter flag `-t` / `--type` to `image list` command
6+
* Expose labels of servers, Floating IPs, images, and SSH Keys
7+
* Add `hcloud {server|ssh-key|image|floating-ip} {add-label|remove-label}` commands
68

79
## v1.6.1
810

Gopkg.lock

Lines changed: 42 additions & 6 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Gopkg.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
[[constraint]]
66
name = "github.com/hetznercloud/hcloud-go"
7-
version = "v1.6.0"
7+
version = "1.9.0"
88

99
[[constraint]]
1010
name = "github.com/pelletier/go-toml"

cli/floatingip.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@ func newFloatingIPCommand(cli *CLI) *cobra.Command {
2121
newFloatingIPDeleteCommand(cli),
2222
newFloatingIPEnableProtectionCommand(cli),
2323
newFloatingIPDisableProtectionCommand(cli),
24+
newFloatingIPAddLabelCommand(cli),
25+
newFloatingIPRemoveLabelCommand(cli),
2426
)
2527
return cmd
2628
}

cli/floatingip_add_label.go

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
package cli
2+
3+
import (
4+
"errors"
5+
"fmt"
6+
"strconv"
7+
8+
"github.com/hetznercloud/hcloud-go/hcloud"
9+
"github.com/spf13/cobra"
10+
)
11+
12+
func newFloatingIPAddLabelCommand(cli *CLI) *cobra.Command {
13+
cmd := &cobra.Command{
14+
Use: "add-label [FLAGS] FLOATINGIP LABEL",
15+
Short: "Add a label to a Floating IP",
16+
Args: cobra.ExactArgs(2),
17+
TraverseChildren: true,
18+
DisableFlagsInUseLine: true,
19+
PreRunE: chainRunE(validateFloatingIPAddLabel, cli.ensureToken),
20+
RunE: cli.wrap(runFloatingIPAddLabel),
21+
}
22+
23+
cmd.Flags().BoolP("overwrite", "o", false, "Overwrite label if it exists already")
24+
return cmd
25+
}
26+
27+
func validateFloatingIPAddLabel(cmd *cobra.Command, args []string) error {
28+
label := splitLabel(args[1])
29+
if len(label) != 2 {
30+
return fmt.Errorf("invalid label: %s", args[1])
31+
}
32+
33+
return nil
34+
}
35+
36+
func runFloatingIPAddLabel(cli *CLI, cmd *cobra.Command, args []string) error {
37+
overwrite, _ := cmd.Flags().GetBool("overwrite")
38+
id, err := strconv.Atoi(args[0])
39+
if err != nil {
40+
return errors.New("invalid Floating IP ID")
41+
}
42+
floatingIP, _, err := cli.Client().FloatingIP.GetByID(cli.Context, id)
43+
if err != nil {
44+
return err
45+
}
46+
if floatingIP == nil {
47+
return fmt.Errorf("Floating IP not found: %d", id)
48+
}
49+
label := splitLabel(args[1])
50+
51+
if _, ok := floatingIP.Labels[label[0]]; ok && !overwrite {
52+
return fmt.Errorf("label %s on Floating IP %d already exists", label[0], floatingIP.ID)
53+
}
54+
labels := floatingIP.Labels
55+
labels[label[0]] = label[1]
56+
opts := hcloud.FloatingIPUpdateOpts{
57+
Labels: labels,
58+
}
59+
_, _, err = cli.Client().FloatingIP.Update(cli.Context, floatingIP, opts)
60+
if err != nil {
61+
return err
62+
}
63+
fmt.Printf("Label %s added to Floating IP %d\n", label[0], floatingIP.ID)
64+
65+
return nil
66+
}

cli/floatingip_describe.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,5 +71,13 @@ func runFloatingIPDescribe(cli *CLI, cmd *cobra.Command, args []string) error {
7171
fmt.Printf("Protection:\n")
7272
fmt.Printf(" Delete:\t%s\n", yesno(floatingIP.Protection.Delete))
7373

74+
fmt.Print("Labels:\n")
75+
if len(floatingIP.Labels) == 0 {
76+
fmt.Print(" No labels\n")
77+
} else {
78+
for key, value := range floatingIP.Labels {
79+
fmt.Printf(" %s: %s\n", key, value)
80+
}
81+
}
7482
return nil
7583
}

cli/floatingip_list.go

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ func newFloatingIPListCommand(cli *CLI) *cobra.Command {
7070
RunE: cli.wrap(runFloatingIPList),
7171
}
7272
addListOutputFlag(cmd, floatingIPListTableOutput.Columns())
73+
cmd.Flags().StringP("selector", "l", "", "Selector to filter by labels")
7374
return cmd
7475
}
7576

@@ -80,7 +81,14 @@ func runFloatingIPList(cli *CLI, cmd *cobra.Command, args []string) error {
8081
return err
8182
}
8283

83-
floatingIPs, err := cli.Client().FloatingIP.All(cli.Context)
84+
labelSelector, _ := cmd.Flags().GetString("selector")
85+
opts := hcloud.FloatingIPListOpts{
86+
ListOpts: hcloud.ListOpts{
87+
LabelSelector: labelSelector,
88+
PerPage: 50,
89+
},
90+
}
91+
floatingIPs, err := cli.Client().FloatingIP.AllWithOpts(cli.Context, opts)
8492
if err != nil {
8593
return err
8694
}

cli/floatingip_remove_label.go

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
package cli
2+
3+
import (
4+
"errors"
5+
"fmt"
6+
"strconv"
7+
8+
"github.com/hetznercloud/hcloud-go/hcloud"
9+
"github.com/spf13/cobra"
10+
)
11+
12+
func newFloatingIPRemoveLabelCommand(cli *CLI) *cobra.Command {
13+
cmd := &cobra.Command{
14+
Use: "remove-label [FLAGS] FLOATINGIP LABELKEY",
15+
Short: "Remove a label from a Floating IP",
16+
Args: cobra.RangeArgs(1, 2),
17+
TraverseChildren: true,
18+
DisableFlagsInUseLine: true,
19+
PreRunE: chainRunE(validateFloatingIPRemoveLabel, cli.ensureToken),
20+
RunE: cli.wrap(runFloatingIPRemoveLabel),
21+
}
22+
23+
cmd.Flags().BoolP("all", "a", false, "Remove all labels")
24+
return cmd
25+
}
26+
27+
func validateFloatingIPRemoveLabel(cmd *cobra.Command, args []string) error {
28+
all, _ := cmd.Flags().GetBool("all")
29+
30+
if all && len(args) == 2 {
31+
return errors.New("must not specify a label key when using --all/-a")
32+
}
33+
if !all && len(args) != 2 {
34+
return errors.New("must specify a label key when not using --all/-a")
35+
}
36+
37+
return nil
38+
}
39+
40+
func runFloatingIPRemoveLabel(cli *CLI, cmd *cobra.Command, args []string) error {
41+
all, _ := cmd.Flags().GetBool("all")
42+
id, err := strconv.Atoi(args[0])
43+
if err != nil {
44+
return errors.New("invalid Floating IP ID")
45+
}
46+
floatingIP, _, err := cli.Client().FloatingIP.GetByID(cli.Context, id)
47+
if err != nil {
48+
return err
49+
}
50+
if floatingIP == nil {
51+
return fmt.Errorf("Floating IP not found: %d", id)
52+
}
53+
54+
labels := floatingIP.Labels
55+
if all {
56+
labels = make(map[string]string)
57+
} else {
58+
label := args[1]
59+
if _, ok := floatingIP.Labels[label]; !ok {
60+
return fmt.Errorf("label %s on Floating IP %d does not exist", label, floatingIP.ID)
61+
}
62+
delete(labels, label)
63+
}
64+
65+
opts := hcloud.FloatingIPUpdateOpts{
66+
Labels: labels,
67+
}
68+
_, _, err = cli.Client().FloatingIP.Update(cli.Context, floatingIP, opts)
69+
if err != nil {
70+
return err
71+
}
72+
73+
if all {
74+
fmt.Printf("All labels removed from Floating IP %d\n", floatingIP.ID)
75+
} else {
76+
fmt.Printf("Label %s removed from Floating IP %d\n", args[1], floatingIP.ID)
77+
}
78+
79+
return nil
80+
}

cli/image.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@ func newImageCommand(cli *CLI) *cobra.Command {
1818
newImageUpdateCommand(cli),
1919
newImageEnableProtectionCommand(cli),
2020
newImageDisableProtectionCommand(cli),
21+
newImageAddLabelCommand(cli),
22+
newImageRemoveLabelCommand(cli),
2123
)
2224
return cmd
2325
}

0 commit comments

Comments
 (0)