forked from cloudfoundry/cli
/
service_instance_list.go
131 lines (117 loc) · 4.38 KB
/
service_instance_list.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
package v7action
import (
"fmt"
"github.com/LukasHeimann/cloudfoundrycli/v8/api/cloudcontroller/ccv3"
"github.com/LukasHeimann/cloudfoundrycli/v8/resources"
"github.com/LukasHeimann/cloudfoundrycli/v8/types"
"github.com/LukasHeimann/cloudfoundrycli/v8/util/batcher"
"github.com/LukasHeimann/cloudfoundrycli/v8/util/extract"
"github.com/LukasHeimann/cloudfoundrycli/v8/util/lookuptable"
"github.com/LukasHeimann/cloudfoundrycli/v8/util/railway"
)
type ServiceInstance struct {
Type resources.ServiceInstanceType
Name string
ServicePlanName string
ServiceOfferingName string
ServiceBrokerName string
BoundApps []string
LastOperation string
UpgradeAvailable types.OptionalBoolean
}
type planDetails struct {
plan, offering, broker string
}
func (actor Actor) GetServiceInstancesForSpace(spaceGUID string, omitApps bool) ([]ServiceInstance, Warnings, error) {
var (
instances []resources.ServiceInstance
bindings []resources.ServiceCredentialBinding
included ccv3.IncludedResources
)
warnings, err := railway.Sequentially(
func() (warnings ccv3.Warnings, err error) {
instances, included, warnings, err = actor.CloudControllerClient.GetServiceInstances(
ccv3.Query{Key: ccv3.SpaceGUIDFilter, Values: []string{spaceGUID}},
ccv3.Query{Key: ccv3.FieldsServicePlan, Values: []string{"guid", "name", "relationships.service_offering"}},
ccv3.Query{Key: ccv3.FieldsServicePlanServiceOffering, Values: []string{"guid", "name", "relationships.service_broker"}},
ccv3.Query{Key: ccv3.FieldsServicePlanServiceOfferingServiceBroker, Values: []string{"guid", "name"}},
ccv3.Query{Key: ccv3.OrderBy, Values: []string{ccv3.NameOrder}},
ccv3.Query{Key: ccv3.PerPage, Values: []string{ccv3.MaxPerPage}},
)
return
},
func() (warnings ccv3.Warnings, err error) {
if !omitApps {
return batcher.RequestByGUID(
extract.UniqueList("GUID", instances),
func(guids []string) (ccv3.Warnings, error) {
batch, warnings, err := actor.CloudControllerClient.GetServiceCredentialBindings(
ccv3.Query{Key: ccv3.ServiceInstanceGUIDFilter, Values: guids},
ccv3.Query{Key: ccv3.Include, Values: []string{"app"}},
)
bindings = append(bindings, batch...)
return warnings, err
},
)
}
return
},
)
if err != nil {
return nil, Warnings(warnings), err
}
planDetailsFromPlanGUIDLookup := buildPlanDetailsLookup(included)
boundAppsNamesFromInstanceGUIDLookup := buildBoundAppsLookup(bindings, spaceGUID)
result := make([]ServiceInstance, len(instances))
for i, instance := range instances {
names := planDetailsFromPlanGUIDLookup[instance.ServicePlanGUID]
result[i] = ServiceInstance{
Name: instance.Name,
Type: instance.Type,
UpgradeAvailable: instance.UpgradeAvailable,
ServicePlanName: names.plan,
ServiceOfferingName: names.offering,
ServiceBrokerName: names.broker,
BoundApps: boundAppsNamesFromInstanceGUIDLookup[instance.GUID],
LastOperation: lastOperation(instance.LastOperation),
}
}
return result, Warnings(warnings), nil
}
func lastOperation(lo resources.LastOperation) string {
if lo.Type != "" && lo.State != "" {
return fmt.Sprintf("%s %s", lo.Type, lo.State)
}
return ""
}
func buildPlanDetailsLookup(included ccv3.IncludedResources) map[string]planDetails {
brokerLookup := lookuptable.NameFromGUID(included.ServiceBrokers)
type twoNames struct{ broker, offering string }
offeringLookup := make(map[string]twoNames)
for _, o := range included.ServiceOfferings {
brokerName := brokerLookup[o.ServiceBrokerGUID]
offeringLookup[o.GUID] = twoNames{
broker: brokerName,
offering: o.Name,
}
}
planLookup := make(map[string]planDetails)
for _, p := range included.ServicePlans {
names := offeringLookup[p.ServiceOfferingGUID]
planLookup[p.GUID] = planDetails{
broker: names.broker,
offering: names.offering,
plan: p.Name,
}
}
return planLookup
}
func buildBoundAppsLookup(bindings []resources.ServiceCredentialBinding, spaceGUID string) map[string][]string {
appsBoundLookup := make(map[string][]string)
for _, binding := range bindings {
if binding.Type == resources.AppBinding && binding.AppSpaceGUID == spaceGUID {
appsBoundLookup[binding.ServiceInstanceGUID] = append(appsBoundLookup[binding.ServiceInstanceGUID], binding.AppName)
}
}
return appsBoundLookup
}