-
Notifications
You must be signed in to change notification settings - Fork 4
/
Copy pathcf_buildpacks_usage_cmd.go
137 lines (114 loc) · 4.18 KB
/
cf_buildpacks_usage_cmd.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
package main
import (
"encoding/json"
"fmt"
"sort"
"strconv"
"strings"
"github.com/cloudfoundry/cli/plugin"
)
// CliBuildpackUsage represents Buildpack Usage CLI interface
type CliBuildpackUsage struct{}
// AppSearchResults represents top level attributes of JSON response from Cloud Foundry API
type AppSearchResults struct {
TotalResults int `json:"total_results"`
TotalPages int `json:"total_pages"`
Resources []AppSearchResources `json:"resources"`
}
// AppSearchResources represents resources attribute of JSON response from Cloud Foundry API
type AppSearchResources struct {
Entity AppSearchEntity `json:"entity"`
}
// AppSearchEntity represents entity attribute of resources attribute within JSON response from Cloud Foundry API
type AppSearchEntity struct {
Name string `json:"name"`
Buildpack string `json:"buildpack"`
DetectedBuildpack string `json:"detected_buildpack"`
}
// GetMetadata provides the Cloud Foundry CLI with metadata to provide user about how to use buildpack-usage command
func (c *CliBuildpackUsage) GetMetadata() plugin.PluginMetadata {
return plugin.PluginMetadata{
Name: "CliBuildpackUsage",
Version: plugin.VersionType{
Major: 1,
Minor: 0,
Build: 0,
},
Commands: []plugin.Command{
{
Name: "buildpack-usage",
HelpText: "Command to view buildpack usage in current CLI target context.",
UsageDetails: plugin.Usage{
Usage: "buildpack-usage\n cf buildpack-usage",
},
},
},
}
}
func main() {
plugin.Start(new(CliBuildpackUsage))
}
// Run is what is executed by the Cloud Foundry CLI when the buildpack-usage command is specified
func (c CliBuildpackUsage) Run(cliConnection plugin.CliConnection, args []string) {
res := c.GetAppData(cliConnection)
var buildpacksUsed sort.StringSlice
for _, val := range res.Resources {
bp := val.Entity.Buildpack
if bp == "" {
bp = val.Entity.DetectedBuildpack
}
buildpacksUsed = append(buildpacksUsed, bp)
}
var buildpackUsageTable = c.CreateBuildpackUsageTable(buildpacksUsed)
c.PrintBuildpacks(buildpackUsageTable, res.TotalResults)
}
// CreateBuildpackUsageTable creates a map whose key is buildpack and value is count of that buildpack
func (c CliBuildpackUsage) CreateBuildpackUsageTable(buildpacksUsed sort.StringSlice) map[string]int {
buildpackUsageCounts := make(map[string]int)
for _, buildpackName := range buildpacksUsed {
if _, ok := buildpackUsageCounts[buildpackName]; ok {
buildpackUsageCounts[buildpackName]++
} else {
buildpackUsageCounts[buildpackName] = 1
}
}
return buildpackUsageCounts
}
// PrintBuildpacks prints the buildpack data to console
func (c CliBuildpackUsage) PrintBuildpacks(buildpackUsageTable map[string]int, totalResults int) {
fmt.Println("")
fmt.Printf("%v buildpacks found across %v app deployments\n\n", len(buildpackUsageTable), totalResults)
fmt.Println("Buildpacks Used\n")
fmt.Println("Count\tName")
fmt.Println("-------------------------------")
buildpackNames := make([]string, len(buildpackUsageTable))
j := 0
for buildpack, _ := range buildpackUsageTable {
buildpackNames[j] = buildpack
j++
}
sort.Strings(buildpackNames)
for _, buildpack := range buildpackNames {
fmt.Printf("%v\t%v\n", buildpackUsageTable[buildpack], buildpack)
}
}
// GetAppData requests all of the Application data from Cloud Foundry
func (c CliBuildpackUsage) GetAppData(cliConnection plugin.CliConnection) AppSearchResults {
var res AppSearchResults
res = c.UnmarshallAppSearchResults("/v2/apps?order-direction=asc&results-per-page=100", cliConnection)
if res.TotalPages > 1 {
for i := 2; i <= res.TotalPages; i++ {
apiUrl := fmt.Sprintf("/v2/apps?order-direction=asc&page=%v&results-per-page=100", strconv.Itoa(i))
tRes := c.UnmarshallAppSearchResults(apiUrl, cliConnection)
res.Resources = append(res.Resources, tRes.Resources...)
}
}
return res
}
func (c CliBuildpackUsage) UnmarshallAppSearchResults(apiUrl string, cliConnection plugin.CliConnection) AppSearchResults {
var tRes AppSearchResults
cmd := []string{"curl", apiUrl}
output, _ := cliConnection.CliCommandWithoutTerminalOutput(cmd...)
json.Unmarshal([]byte(strings.Join(output, "")), &tRes)
return tRes
}