-
Notifications
You must be signed in to change notification settings - Fork 6
/
oei_reporter.go
134 lines (109 loc) · 3.35 KB
/
oei_reporter.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
package reporter
import (
"sort"
"code.cloudfoundry.org/cpu-entitlement-plugin/cf"
"code.cloudfoundry.org/cpu-entitlement-plugin/fetchers"
"code.cloudfoundry.org/lager"
)
type OEIReport struct {
Org string
Username string
SpaceReports []SpaceReport
}
type SpaceReport struct {
SpaceName string
Apps []string
}
//go:generate counterfeiter . MetricsFetcher
type MetricsFetcher interface {
FetchInstanceData(logger lager.Logger, appGuid string, appInstances map[int]cf.Instance) (map[int]interface{}, error)
}
//go:generate counterfeiter . CloudFoundryClient
type CloudFoundryClient interface {
GetSpaces(logger lager.Logger) ([]cf.Space, error)
GetCurrentOrg(logger lager.Logger) (string, error)
Username(logger lager.Logger) (string, error)
}
type OverEntitlementInstances struct {
cf CloudFoundryClient
metricsFetcher MetricsFetcher
}
func NewOverEntitlementInstances(cf CloudFoundryClient, metricsFetcher MetricsFetcher) OverEntitlementInstances {
return OverEntitlementInstances{
cf: cf,
metricsFetcher: metricsFetcher,
}
}
func (r OverEntitlementInstances) OverEntitlementInstances(logger lager.Logger) (OEIReport, error) {
logger = logger.Session("oei-reporter")
logger.Info("start")
defer logger.Info("end")
org, err := r.cf.GetCurrentOrg(logger)
if err != nil {
return OEIReport{}, err
}
user, err := r.cf.Username(logger)
if err != nil {
return OEIReport{}, err
}
spaces, err := r.cf.GetSpaces(logger)
if err != nil {
return OEIReport{}, err
}
spaceReports, err := r.buildSpaceReports(logger, spaces)
if err != nil {
return OEIReport{}, err
}
return OEIReport{Org: org, Username: user, SpaceReports: spaceReports}, nil
}
func (r OverEntitlementInstances) buildSpaceReports(logger lager.Logger, spaces []cf.Space) ([]SpaceReport, error) {
spaceReports := []SpaceReport{}
for _, space := range spaces {
apps, err := r.filterApps(logger, space.Applications)
if err != nil {
return nil, err
}
if len(apps) == 0 {
continue
}
sort.Strings(apps)
spaceReports = append(spaceReports, SpaceReport{SpaceName: space.Name, Apps: apps})
}
sort.Slice(spaceReports, func(i, j int) bool {
return spaceReports[i].SpaceName < spaceReports[j].SpaceName
})
return spaceReports, nil
}
func (r OverEntitlementInstances) filterApps(logger lager.Logger, spaceApps []cf.Application) ([]string, error) {
apps := []string{}
for _, app := range spaceApps {
isOverEntitlement, err := r.isOverEntitlement(logger, app.Guid, app.Instances)
if err != nil {
return nil, err
}
if isOverEntitlement {
apps = append(apps, app.Name)
}
}
return apps, nil
}
func (r OverEntitlementInstances) isOverEntitlement(logger lager.Logger, appGuid string, appInstances map[int]cf.Instance) (bool, error) {
logger = logger.Session("is-over-entitlement", lager.Data{"app-guid": appGuid})
appInstancesUsages, err := r.metricsFetcher.FetchInstanceData(logger, appGuid, appInstances)
if err != nil {
return false, err
}
isOverEntitlement := false
for _, instanceData := range appInstancesUsages {
cumulativeInstanceData, ok := instanceData.(fetchers.CumulativeInstanceData)
if !ok {
logger.Info("metrics-fetcher-returned-wrong-type",
lager.Data{"instance-data": instanceData})
continue
}
if cumulativeInstanceData.Usage > 1 {
isOverEntitlement = true
}
}
return isOverEntitlement, nil
}