1package firewall
2
3import (
4	"github.com/hetznercloud/cli/internal/cmd/output"
5	"github.com/hetznercloud/cli/internal/cmd/util"
6	"github.com/hetznercloud/cli/internal/state"
7	"github.com/hetznercloud/hcloud-go/hcloud"
8	"github.com/hetznercloud/hcloud-go/hcloud/schema"
9	"github.com/spf13/cobra"
10)
11
12var listTableOutput *output.Table
13
14func init() {
15	listTableOutput = output.NewTable().
16		AddAllowedFields(hcloud.Firewall{})
17}
18
19func newListCommand(cli *state.State) *cobra.Command {
20	cmd := &cobra.Command{
21		Use:   "list [FLAGS]",
22		Short: "List Firewalls",
23		Long: util.ListLongDescription(
24			"Displays a list of Firewalls.",
25			listTableOutput.Columns(),
26		),
27		TraverseChildren:      true,
28		DisableFlagsInUseLine: true,
29		PreRunE:               cli.EnsureToken,
30		RunE:                  cli.Wrap(runList),
31	}
32	output.AddFlag(cmd, output.OptionNoHeader(), output.OptionColumns(listTableOutput.Columns()), output.OptionJSON())
33	return cmd
34}
35
36func runList(cli *state.State, cmd *cobra.Command, args []string) error {
37	outOpts := output.FlagsForCommand(cmd)
38
39	firewalls, err := cli.Client().Firewall.All(cli.Context)
40	if err != nil {
41		return err
42	}
43
44	if outOpts.IsSet("json") {
45		var firewallSchemas []schema.Firewall
46		for _, firewall := range firewalls {
47			firewallSchema := schema.Firewall{
48				ID:      firewall.ID,
49				Name:    firewall.Name,
50				Labels:  firewall.Labels,
51				Created: firewall.Created,
52			}
53			for _, rule := range firewall.Rules {
54				var sourceNets []string
55				for _, sourceIP := range rule.SourceIPs {
56					sourceNets = append(sourceNets, sourceIP.Network())
57				}
58				var destinationNets []string
59				for _, destinationIP := range rule.DestinationIPs {
60					destinationNets = append(destinationNets, destinationIP.Network())
61				}
62				firewallSchema.Rules = append(firewallSchema.Rules, schema.FirewallRule{
63					Direction:      string(rule.Direction),
64					SourceIPs:      sourceNets,
65					DestinationIPs: destinationNets,
66					Protocol:       string(rule.Protocol),
67					Port:           rule.Port,
68				})
69			}
70			for _, AppliedTo := range firewall.AppliedTo {
71				s := schema.FirewallResource{
72					Type: string(AppliedTo.Type),
73				}
74				switch AppliedTo.Type {
75				case hcloud.FirewallResourceTypeServer:
76					s.Server = &schema.FirewallResourceServer{ID: AppliedTo.Server.ID}
77				}
78				firewallSchema.AppliedTo = append(firewallSchema.AppliedTo, s)
79			}
80
81			firewallSchemas = append(firewallSchemas, firewallSchema)
82		}
83		return util.DescribeJSON(firewallSchemas)
84	}
85
86	cols := []string{"id", "name"}
87	if outOpts.IsSet("columns") {
88		cols = outOpts["columns"]
89	}
90
91	tw := listTableOutput
92	if err = tw.ValidateColumns(cols); err != nil {
93		return err
94	}
95
96	if !outOpts.IsSet("noheader") {
97		tw.WriteHeader(cols)
98	}
99	for _, firewall := range firewalls {
100		tw.Write(cols, firewall)
101	}
102	tw.Flush()
103
104	return nil
105}
106