github.com/pf-qiu/concourse/v6@v6.7.3-0.20201207032516-1f455d73275f/fly/commands/volumes.go (about) 1 package commands 2 3 import ( 4 "fmt" 5 "os" 6 "sort" 7 "strings" 8 9 "sigs.k8s.io/yaml" 10 11 "github.com/pf-qiu/concourse/v6/atc" 12 "github.com/pf-qiu/concourse/v6/fly/commands/internal/displayhelpers" 13 "github.com/pf-qiu/concourse/v6/fly/rc" 14 "github.com/pf-qiu/concourse/v6/fly/ui" 15 "github.com/fatih/color" 16 ) 17 18 type VolumesCommand struct { 19 Details bool `short:"d" long:"details" description:"Print additional information for each volume"` 20 Json bool `long:"json" description:"Print command result as JSON"` 21 } 22 23 func (command *VolumesCommand) Execute([]string) error { 24 target, err := rc.LoadTarget(Fly.Target, Fly.Verbose) 25 if err != nil { 26 return err 27 } 28 29 err = target.Validate() 30 if err != nil { 31 return err 32 } 33 34 volumes, err := target.Team().ListVolumes() 35 if err != nil { 36 return err 37 } 38 39 if command.Json { 40 err = displayhelpers.JsonPrint(volumes) 41 if err != nil { 42 return err 43 } 44 return nil 45 } 46 47 table := ui.Table{ 48 Headers: ui.TableRow{ 49 {Contents: "handle", Color: color.New(color.Bold)}, 50 {Contents: "worker", Color: color.New(color.Bold)}, 51 {Contents: "type", Color: color.New(color.Bold)}, 52 {Contents: "identifier", Color: color.New(color.Bold)}, 53 }, 54 } 55 56 sort.Sort(volumesByWorkerAndHandle(volumes)) 57 58 for _, c := range volumes { 59 row := ui.TableRow{ 60 {Contents: c.ID}, 61 {Contents: c.WorkerName}, 62 {Contents: c.Type}, 63 {Contents: command.volumeIdentifier(c)}, 64 } 65 66 table.Data = append(table.Data, row) 67 } 68 69 return table.Render(os.Stdout, Fly.PrintTableHeaders) 70 } 71 72 func (command *VolumesCommand) volumeIdentifier(volume atc.Volume) string { 73 switch volume.Type { 74 case "container": 75 if command.Details { 76 identifier := fmt.Sprintf("container:%s,path:%s", volume.ContainerHandle, volume.Path) 77 if volume.ParentHandle != "" { 78 identifier = fmt.Sprintf("%s,parent:%s", identifier, volume.ParentHandle) 79 } 80 return identifier 81 } 82 83 return volume.ContainerHandle 84 case "task-cache": 85 return fmt.Sprintf("%s/%s/%s", volume.PipelineName, volume.JobName, volume.StepName) 86 case "resource": 87 if command.Details { 88 return presentResourceType(volume.ResourceType) 89 } 90 return presentMap(volume.ResourceType.Version) 91 case "resource-type": 92 if command.Details { 93 return presentMap(volume.BaseResourceType) 94 } 95 return volume.BaseResourceType.Name 96 } 97 98 return "n/a" 99 } 100 101 func presentMap(version interface{}) string { 102 marshalled, _ := yaml.Marshal(version) 103 lines := strings.Split(strings.TrimSpace(string(marshalled)), "\n") 104 return strings.Replace(strings.Join(lines, ","), " ", "", -1) 105 } 106 107 func presentResourceType(resourceType *atc.VolumeResourceType) string { 108 if resourceType.BaseResourceType != nil { 109 return presentMap(resourceType.BaseResourceType) 110 } 111 112 if resourceType.ResourceType != nil { 113 innerResourceType := presentResourceType(resourceType.ResourceType) 114 version := presentMap(resourceType.Version) 115 return fmt.Sprintf("type:resource(%s),version:%s", innerResourceType, version) 116 } 117 118 return "" 119 } 120 121 type volumesByWorkerAndHandle []atc.Volume 122 123 func (cs volumesByWorkerAndHandle) Len() int { return len(cs) } 124 func (cs volumesByWorkerAndHandle) Swap(i int, j int) { cs[i], cs[j] = cs[j], cs[i] } 125 func (cs volumesByWorkerAndHandle) Less(i int, j int) bool { 126 if cs[i].WorkerName == cs[j].WorkerName { 127 return cs[i].ID < cs[j].ID 128 } 129 130 return cs[i].WorkerName < cs[j].WorkerName 131 }