github.com/DaAlbrecht/cf-cli@v0.0.0-20231128151943-1fe19bb400b9/actor/v7action/service_instance_list.go (about) 1 package v7action 2 3 import ( 4 "fmt" 5 6 "code.cloudfoundry.org/cli/api/cloudcontroller/ccv3" 7 "code.cloudfoundry.org/cli/resources" 8 "code.cloudfoundry.org/cli/types" 9 "code.cloudfoundry.org/cli/util/batcher" 10 "code.cloudfoundry.org/cli/util/extract" 11 "code.cloudfoundry.org/cli/util/lookuptable" 12 "code.cloudfoundry.org/cli/util/railway" 13 ) 14 15 type ServiceInstance struct { 16 Type resources.ServiceInstanceType 17 Name string 18 ServicePlanName string 19 ServiceOfferingName string 20 ServiceBrokerName string 21 BoundApps []string 22 LastOperation string 23 UpgradeAvailable types.OptionalBoolean 24 } 25 26 type planDetails struct { 27 plan, offering, broker string 28 } 29 30 func (actor Actor) GetServiceInstancesForSpace(spaceGUID string, omitApps bool) ([]ServiceInstance, Warnings, error) { 31 var ( 32 instances []resources.ServiceInstance 33 bindings []resources.ServiceCredentialBinding 34 included ccv3.IncludedResources 35 ) 36 37 warnings, err := railway.Sequentially( 38 func() (warnings ccv3.Warnings, err error) { 39 instances, included, warnings, err = actor.CloudControllerClient.GetServiceInstances( 40 ccv3.Query{Key: ccv3.SpaceGUIDFilter, Values: []string{spaceGUID}}, 41 ccv3.Query{Key: ccv3.FieldsServicePlan, Values: []string{"guid", "name", "relationships.service_offering"}}, 42 ccv3.Query{Key: ccv3.FieldsServicePlanServiceOffering, Values: []string{"guid", "name", "relationships.service_broker"}}, 43 ccv3.Query{Key: ccv3.FieldsServicePlanServiceOfferingServiceBroker, Values: []string{"guid", "name"}}, 44 ccv3.Query{Key: ccv3.OrderBy, Values: []string{ccv3.NameOrder}}, 45 ccv3.Query{Key: ccv3.PerPage, Values: []string{ccv3.MaxPerPage}}, 46 ) 47 return 48 }, 49 func() (warnings ccv3.Warnings, err error) { 50 if !omitApps { 51 return batcher.RequestByGUID( 52 extract.UniqueList("GUID", instances), 53 func(guids []string) (ccv3.Warnings, error) { 54 batch, warnings, err := actor.CloudControllerClient.GetServiceCredentialBindings( 55 ccv3.Query{Key: ccv3.ServiceInstanceGUIDFilter, Values: guids}, 56 ccv3.Query{Key: ccv3.Include, Values: []string{"app"}}, 57 ) 58 bindings = append(bindings, batch...) 59 return warnings, err 60 }, 61 ) 62 } 63 return 64 }, 65 ) 66 if err != nil { 67 return nil, Warnings(warnings), err 68 } 69 70 planDetailsFromPlanGUIDLookup := buildPlanDetailsLookup(included) 71 boundAppsNamesFromInstanceGUIDLookup := buildBoundAppsLookup(bindings, spaceGUID) 72 73 result := make([]ServiceInstance, len(instances)) 74 for i, instance := range instances { 75 names := planDetailsFromPlanGUIDLookup[instance.ServicePlanGUID] 76 result[i] = ServiceInstance{ 77 Name: instance.Name, 78 Type: instance.Type, 79 UpgradeAvailable: instance.UpgradeAvailable, 80 ServicePlanName: names.plan, 81 ServiceOfferingName: names.offering, 82 ServiceBrokerName: names.broker, 83 BoundApps: boundAppsNamesFromInstanceGUIDLookup[instance.GUID], 84 LastOperation: lastOperation(instance.LastOperation), 85 } 86 } 87 88 return result, Warnings(warnings), nil 89 } 90 91 func lastOperation(lo resources.LastOperation) string { 92 if lo.Type != "" && lo.State != "" { 93 return fmt.Sprintf("%s %s", lo.Type, lo.State) 94 } 95 return "" 96 } 97 98 func buildPlanDetailsLookup(included ccv3.IncludedResources) map[string]planDetails { 99 brokerLookup := lookuptable.NameFromGUID(included.ServiceBrokers) 100 101 type twoNames struct{ broker, offering string } 102 offeringLookup := make(map[string]twoNames) 103 for _, o := range included.ServiceOfferings { 104 brokerName := brokerLookup[o.ServiceBrokerGUID] 105 offeringLookup[o.GUID] = twoNames{ 106 broker: brokerName, 107 offering: o.Name, 108 } 109 } 110 111 planLookup := make(map[string]planDetails) 112 for _, p := range included.ServicePlans { 113 names := offeringLookup[p.ServiceOfferingGUID] 114 planLookup[p.GUID] = planDetails{ 115 broker: names.broker, 116 offering: names.offering, 117 plan: p.Name, 118 } 119 } 120 return planLookup 121 } 122 123 func buildBoundAppsLookup(bindings []resources.ServiceCredentialBinding, spaceGUID string) map[string][]string { 124 appsBoundLookup := make(map[string][]string) 125 for _, binding := range bindings { 126 if binding.Type == resources.AppBinding && binding.AppSpaceGUID == spaceGUID { 127 appsBoundLookup[binding.ServiceInstanceGUID] = append(appsBoundLookup[binding.ServiceInstanceGUID], binding.AppName) 128 } 129 } 130 return appsBoundLookup 131 }