// Show condensed details of multiple servers // @client: authenticated CLCv2 Client // @servnames: server names func showServers(client *clcv2.CLIClient, servnames ...string) { var truncate = func(s string, maxlen int) string { if len(s) >= maxlen { s = s[:maxlen] } return s } table := tablewriter.NewWriter(os.Stdout) table.SetAutoFormatHeaders(false) table.SetAlignment(tablewriter.ALIGN_LEFT) table.SetAutoWrapText(true) table.SetHeader([]string{ "Name", "Group", "Description", "OS", "IP", "CPU", "Mem", "Storage", "Status", "Last Change", }) for _, servname := range servnames { server, err := client.GetServer(servname) if err != nil { fmt.Fprintf(os.Stderr, "Failed to list details of server %q: %s", servname, err) continue } grp, err := client.GetGroup(server.GroupId) if err != nil { exit.Fatalf("failed to resolve %s group UUID: %s", servname, err) } IPs := []string{} for _, ip := range server.Details.IpAddresses { if ip.Public != "" { IPs = append(IPs, ip.Public) } if ip.Internal != "" { IPs = append(IPs, ip.Internal) } } status := server.Details.PowerState if server.Details.InMaintenanceMode { status = "MAINTENANCE" } else if server.Status != "active" { status = server.Status } desc := server.Description if server.IsTemplate { desc = "TPL: " + desc } modifiedStr := humanize.Time(server.ChangeInfo.ModifiedDate) /* The ModifiedBy field can be an email address, or an API Key (hex string) */ if _, err := hex.DecodeString(server.ChangeInfo.ModifiedBy); err == nil { modifiedStr += " via API Key" } else { modifiedStr += " by " + truncate(server.ChangeInfo.ModifiedBy, 6) } // Append a tilde (~) to indicate it has snapshots serverName := server.Name if len(server.Details.Snapshots) > 0 { serverName += "~" } table.Append([]string{ serverName, grp.Name, truncate(desc, 30), truncate(server.OsType, 15), strings.Join(IPs, " "), fmt.Sprint(server.Details.Cpu), fmt.Sprintf("%d G", server.Details.MemoryMb/1024), fmt.Sprintf("%d G", server.Details.StorageGb), status, modifiedStr, }) } table.Render() }
// Show details of a single server // @client: authenticated CLCv2 Client // @servname: server name func showServer(client *clcv2.CLIClient, servname string) { server, err := client.GetServer(servname) if err != nil { exit.Fatalf("failed to list details of server %q: %s", servname, err) } grp, err := client.GetGroup(server.GroupId) if err != nil { exit.Fatalf("failed to resolve group UUID: %s", err) } /* First public, then private */ IPs := []string{} for _, ip := range server.Details.IpAddresses { if ip.Public != "" { IPs = append(IPs, ip.Public) } } for _, ip := range server.Details.IpAddresses { if ip.Internal != "" { IPs = append(IPs, ip.Internal) } } table := tablewriter.NewWriter(os.Stdout) table.SetAutoFormatHeaders(false) table.SetAlignment(tablewriter.ALIGN_LEFT) table.SetAutoWrapText(true) // CPU, Memory, IP and Power status are not filled in until the server reaches 'active' state. if server.Status == "active" { table.SetHeader([]string{ "Name", "Group", "Description", "OS", "CPU", "Mem", "IP", "Power", "Last Change", }) } else { table.SetHeader([]string{ "Name", "Group", "Description", "OS", "Status", "Owner", "Last Change", }) } modifiedStr := humanize.Time(server.ChangeInfo.ModifiedDate) /* The ModifiedBy field can be an email address, or an API Key (hex string) */ if _, err := hex.DecodeString(server.ChangeInfo.ModifiedBy); err == nil { modifiedStr += " via API Key" } else if len(server.ChangeInfo.ModifiedBy) > 6 { modifiedStr += " by " + server.ChangeInfo.ModifiedBy[:6] } else { modifiedStr += " by " + server.ChangeInfo.ModifiedBy } if server.Status == "active" { table.Append([]string{ server.Name, grp.Name, server.Description, server.OsType, fmt.Sprint(server.Details.Cpu), fmt.Sprintf("%d G", server.Details.MemoryMb/1024), strings.Join(IPs, " "), server.Details.PowerState, modifiedStr, }) } else { table.Append([]string{ server.Name, grp.Name, server.Description, server.OsType, server.Status, server.ChangeInfo.CreatedBy, modifiedStr, }) } table.Render() // Disks if len(server.Details.Disks) > 0 { fmt.Printf("\nDisks of %s (total storage: %d GB)\n", server.Name, server.Details.StorageGb) table = tablewriter.NewWriter(os.Stdout) table.SetAutoFormatHeaders(false) table.SetAlignment(tablewriter.ALIGN_RIGHT) table.SetAutoWrapText(true) table.SetHeader([]string{"Disk ID", "Disk Size/GB", "Paths"}) for _, d := range server.Details.Disks { table.Append([]string{d.Id, fmt.Sprint(d.SizeGB), strings.Join(d.PartitionPaths, ", ")}) } table.Render() } // Partitions if len(server.Details.Partitions) > 0 { fmt.Printf("\nPartitions of %s:\n", server.Name) table = tablewriter.NewWriter(os.Stdout) table.SetAutoFormatHeaders(false) table.SetAlignment(tablewriter.ALIGN_RIGHT) table.SetAutoWrapText(true) table.SetHeader([]string{"Partition Path", "Partition Size/GB"}) for _, p := range server.Details.Partitions { table.Append([]string{p.Path, fmt.Sprintf("%.1f", p.SizeGB)}) } table.Render() } // Snapshots if len(server.Details.Snapshots) > 0 { fmt.Println() table = tablewriter.NewWriter(os.Stdout) table.SetAutoFormatHeaders(false) table.SetAlignment(tablewriter.ALIGN_CENTRE) table.SetAutoWrapText(true) table.SetHeader([]string{fmt.Sprintf("Snapshots of %s", server.Name)}) for _, s := range server.Details.Snapshots { table.Append([]string{s.Name}) } table.Render() } }