1package floatingip
2
3import (
4	"fmt"
5	"strings"
6
7	"github.com/hetznercloud/cli/internal/cmd/output"
8	"github.com/hetznercloud/cli/internal/cmd/util"
9	"github.com/hetznercloud/cli/internal/state"
10	"github.com/hetznercloud/hcloud-go/hcloud/schema"
11
12	"github.com/hetznercloud/hcloud-go/hcloud"
13	"github.com/spf13/cobra"
14)
15
16var listTableOutput *output.Table
17
18func init() {
19	listTableOutput = describeListTableOutput(nil)
20}
21
22func newListCommand(cli *state.State) *cobra.Command {
23	cmd := &cobra.Command{
24		Use:   "list [FLAGS]",
25		Short: "List Floating IPs",
26		Long: util.ListLongDescription(
27			"Displays a list of Floating IPs.",
28			listTableOutput.Columns(),
29		),
30		TraverseChildren:      true,
31		DisableFlagsInUseLine: true,
32		PreRunE:               cli.EnsureToken,
33		RunE:                  cli.Wrap(runList),
34	}
35	output.AddFlag(cmd, output.OptionNoHeader(), output.OptionColumns(listTableOutput.Columns()), output.OptionJSON())
36	cmd.Flags().StringP("selector", "l", "", "Selector to filter by labels")
37	return cmd
38}
39
40func runList(cli *state.State, cmd *cobra.Command, args []string) error {
41	outOpts := output.FlagsForCommand(cmd)
42
43	labelSelector, _ := cmd.Flags().GetString("selector")
44	opts := hcloud.FloatingIPListOpts{
45		ListOpts: hcloud.ListOpts{
46			LabelSelector: labelSelector,
47			PerPage:       50,
48		},
49	}
50	floatingIPs, err := cli.Client().FloatingIP.AllWithOpts(cli.Context, opts)
51	if err != nil {
52		return err
53	}
54
55	if outOpts.IsSet("json") {
56		var floatingIPSchemas []schema.FloatingIP
57		for _, floatingIP := range floatingIPs {
58			floatingIPSchema := schema.FloatingIP{
59				ID:           floatingIP.ID,
60				Name:         floatingIP.Name,
61				Description:  hcloud.String(floatingIP.Description),
62				IP:           floatingIP.IP.String(),
63				Created:      floatingIP.Created,
64				Type:         string(floatingIP.Type),
65				HomeLocation: util.LocationToSchema(*floatingIP.HomeLocation),
66				Blocked:      floatingIP.Blocked,
67				Protection:   schema.FloatingIPProtection{Delete: floatingIP.Protection.Delete},
68				Labels:       floatingIP.Labels,
69			}
70			for ip, dnsPtr := range floatingIP.DNSPtr {
71				floatingIPSchema.DNSPtr = append(floatingIPSchema.DNSPtr, schema.FloatingIPDNSPtr{
72					IP:     ip,
73					DNSPtr: dnsPtr,
74				})
75			}
76			if floatingIP.Server != nil {
77				floatingIPSchema.Server = hcloud.Int(floatingIP.Server.ID)
78			}
79			floatingIPSchemas = append(floatingIPSchemas, floatingIPSchema)
80		}
81		return util.DescribeJSON(floatingIPSchemas)
82	}
83
84	cols := []string{"id", "type", "name", "description", "ip", "home", "server", "dns"}
85	if outOpts.IsSet("columns") {
86		cols = outOpts["columns"]
87	}
88
89	tw := describeListTableOutput(cli)
90	if err = tw.ValidateColumns(cols); err != nil {
91		return err
92	}
93
94	if !outOpts.IsSet("noheader") {
95		tw.WriteHeader(cols)
96	}
97	for _, floatingIP := range floatingIPs {
98		tw.Write(cols, floatingIP)
99	}
100	tw.Flush()
101	return nil
102}
103
104func describeListTableOutput(cli *state.State) *output.Table {
105	return output.NewTable().
106		AddAllowedFields(hcloud.FloatingIP{}).
107		AddFieldFn("dns", output.FieldFn(func(obj interface{}) string {
108			floatingIP := obj.(*hcloud.FloatingIP)
109			var dns string
110			if len(floatingIP.DNSPtr) == 1 {
111				for _, v := range floatingIP.DNSPtr {
112					dns = v
113				}
114			}
115			if len(floatingIP.DNSPtr) > 1 {
116				dns = fmt.Sprintf("%d entries", len(floatingIP.DNSPtr))
117			}
118			return util.NA(dns)
119		})).
120		AddFieldFn("server", output.FieldFn(func(obj interface{}) string {
121			floatingIP := obj.(*hcloud.FloatingIP)
122			var server string
123			if floatingIP.Server != nil && cli != nil {
124				return cli.ServerName(floatingIP.Server.ID)
125			}
126			return util.NA(server)
127		})).
128		AddFieldFn("home", output.FieldFn(func(obj interface{}) string {
129			floatingIP := obj.(*hcloud.FloatingIP)
130			return floatingIP.HomeLocation.Name
131		})).
132		AddFieldFn("ip", output.FieldFn(func(obj interface{}) string {
133			floatingIP := obj.(*hcloud.FloatingIP)
134			if floatingIP.Network != nil {
135				return floatingIP.Network.String()
136			}
137			return floatingIP.IP.String()
138		})).
139		AddFieldFn("protection", output.FieldFn(func(obj interface{}) string {
140			floatingIP := obj.(*hcloud.FloatingIP)
141			var protection []string
142			if floatingIP.Protection.Delete {
143				protection = append(protection, "delete")
144			}
145			return strings.Join(protection, ", ")
146		})).
147		AddFieldFn("labels", output.FieldFn(func(obj interface{}) string {
148			floatingIP := obj.(*hcloud.FloatingIP)
149			return util.LabelsToString(floatingIP.Labels)
150		})).
151		AddFieldFn("created", output.FieldFn(func(obj interface{}) string {
152			floatingIP := obj.(*hcloud.FloatingIP)
153			return util.Datetime(floatingIP.Created)
154		}))
155}
156