1package server 2 3import ( 4 "strconv" 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 servers", 26 Long: util.ListLongDescription( 27 "Displays a list of servers.", 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.ServerListOpts{ 45 ListOpts: hcloud.ListOpts{ 46 LabelSelector: labelSelector, 47 PerPage: 50, 48 }, 49 } 50 servers, err := cli.Client().Server.AllWithOpts(cli.Context, opts) 51 if err != nil { 52 return err 53 } 54 55 if outOpts.IsSet("json") { 56 var serversSchema []schema.Server 57 for _, server := range servers { 58 serverSchema := schema.Server{ 59 ID: server.ID, 60 Name: server.Name, 61 Status: string(server.Status), 62 Created: server.Created, 63 Datacenter: util.DatacenterToSchema(*server.Datacenter), 64 ServerType: util.ServerTypeToSchema(*server.ServerType), 65 PublicNet: schema.ServerPublicNet{ 66 IPv4: schema.ServerPublicNetIPv4{ 67 IP: server.PublicNet.IPv4.IP.String(), 68 Blocked: server.PublicNet.IPv4.Blocked, 69 DNSPtr: server.PublicNet.IPv4.DNSPtr, 70 }, 71 IPv6: schema.ServerPublicNetIPv6{ 72 IP: server.PublicNet.IPv6.IP.String(), 73 Blocked: server.PublicNet.IPv6.Blocked, 74 }, 75 }, 76 RescueEnabled: server.RescueEnabled, 77 BackupWindow: hcloud.String(server.BackupWindow), 78 OutgoingTraffic: &server.OutgoingTraffic, 79 IngoingTraffic: &server.IngoingTraffic, 80 IncludedTraffic: server.IncludedTraffic, 81 Protection: schema.ServerProtection{ 82 Delete: server.Protection.Delete, 83 Rebuild: server.Protection.Rebuild, 84 }, 85 Labels: server.Labels, 86 PrimaryDiskSize: server.PrimaryDiskSize, 87 } 88 if server.Image != nil { 89 serverImage := util.ImageToSchema(*server.Image) 90 serverSchema.Image = &serverImage 91 } 92 if server.ISO != nil { 93 serverISO := util.ISOToSchema(*server.ISO) 94 serverSchema.ISO = &serverISO 95 } 96 for ip, dnsPTR := range server.PublicNet.IPv6.DNSPtr { 97 serverSchema.PublicNet.IPv6.DNSPtr = append(serverSchema.PublicNet.IPv6.DNSPtr, schema.ServerPublicNetIPv6DNSPtr{ 98 IP: ip, 99 DNSPtr: dnsPTR, 100 }) 101 } 102 for _, floatingIP := range server.PublicNet.FloatingIPs { 103 serverSchema.PublicNet.FloatingIPs = append(serverSchema.PublicNet.FloatingIPs, floatingIP.ID) 104 } 105 for _, volume := range server.Volumes { 106 serverSchema.Volumes = append(serverSchema.Volumes, volume.ID) 107 } 108 for _, privateNet := range server.PrivateNet { 109 privateNetSchema := schema.ServerPrivateNet{ 110 Network: privateNet.Network.ID, 111 IP: privateNet.IP.String(), 112 MACAddress: privateNet.MACAddress, 113 } 114 for _, aliasIP := range privateNet.Aliases { 115 privateNetSchema.AliasIPs = append(privateNetSchema.AliasIPs, aliasIP.String()) 116 } 117 serverSchema.PrivateNet = append(serverSchema.PrivateNet, privateNetSchema) 118 } 119 serversSchema = append(serversSchema, serverSchema) 120 } 121 return util.DescribeJSON(serversSchema) 122 } 123 124 cols := []string{"id", "name", "status", "ipv4", "ipv6", "datacenter"} 125 if outOpts.IsSet("columns") { 126 cols = outOpts["columns"] 127 } 128 129 tw := describeListTableOutput(cli) 130 if err = tw.ValidateColumns(cols); err != nil { 131 return err 132 } 133 134 if !outOpts.IsSet("noheader") { 135 tw.WriteHeader(cols) 136 } 137 for _, server := range servers { 138 tw.Write(cols, server) 139 } 140 tw.Flush() 141 return nil 142} 143 144func describeListTableOutput(cli *state.State) *output.Table { 145 return output.NewTable(). 146 AddAllowedFields(hcloud.Server{}). 147 AddFieldFn("ipv4", output.FieldFn(func(obj interface{}) string { 148 server := obj.(*hcloud.Server) 149 return server.PublicNet.IPv4.IP.String() 150 })). 151 AddFieldFn("ipv6", output.FieldFn(func(obj interface{}) string { 152 server := obj.(*hcloud.Server) 153 return server.PublicNet.IPv6.Network.String() 154 })). 155 AddFieldFn("datacenter", output.FieldFn(func(obj interface{}) string { 156 server := obj.(*hcloud.Server) 157 return server.Datacenter.Name 158 })). 159 AddFieldFn("location", output.FieldFn(func(obj interface{}) string { 160 server := obj.(*hcloud.Server) 161 return server.Datacenter.Location.Name 162 })). 163 AddFieldFn("labels", output.FieldFn(func(obj interface{}) string { 164 server := obj.(*hcloud.Server) 165 return util.LabelsToString(server.Labels) 166 })). 167 AddFieldFn("type", output.FieldFn(func(obj interface{}) string { 168 server := obj.(*hcloud.Server) 169 return server.ServerType.Name 170 })). 171 AddFieldFn("volumes", output.FieldFn(func(obj interface{}) string { 172 server := obj.(*hcloud.Server) 173 var volumes []string 174 for _, volume := range server.Volumes { 175 volumeID := strconv.Itoa(volume.ID) 176 volumes = append(volumes, volumeID) 177 } 178 return strings.Join(volumes, ", ") 179 })). 180 AddFieldFn("private_net", output.FieldFn(func(obj interface{}) string { 181 server := obj.(*hcloud.Server) 182 var networks []string 183 if cli != nil { 184 for _, network := range server.PrivateNet { 185 networks = append(networks, cli.NetworkName(network.Network.ID)) 186 } 187 } 188 return util.NA(strings.Join(networks, ", ")) 189 })). 190 AddFieldFn("protection", output.FieldFn(func(obj interface{}) string { 191 server := obj.(*hcloud.Server) 192 var protection []string 193 if server.Protection.Delete { 194 protection = append(protection, "delete") 195 } 196 if server.Protection.Rebuild { 197 protection = append(protection, "rebuild") 198 } 199 return strings.Join(protection, ", ") 200 })). 201 AddFieldFn("created", output.FieldFn(func(obj interface{}) string { 202 server := obj.(*hcloud.Server) 203 return util.Datetime(server.Created) 204 })) 205} 206