github.com/mook-as/cf-cli@v7.0.0-beta.28.0.20200120190804-b91c115fae48+incompatible/cf/actors/planbuilder/plan_builder.go (about) 1 package planbuilder 2 3 import ( 4 "code.cloudfoundry.org/cli/cf/api" 5 "code.cloudfoundry.org/cli/cf/api/organizations" 6 "code.cloudfoundry.org/cli/cf/models" 7 ) 8 9 //go:generate counterfeiter . PlanBuilder 10 11 type PlanBuilder interface { 12 AttachOrgsToPlans([]models.ServicePlanFields) ([]models.ServicePlanFields, error) 13 AttachOrgToPlans([]models.ServicePlanFields, string) ([]models.ServicePlanFields, error) 14 GetPlansForServiceForOrg(string, string) ([]models.ServicePlanFields, error) 15 GetPlansForServiceWithOrgs(string) ([]models.ServicePlanFields, error) 16 GetPlansForManyServicesWithOrgs([]string) ([]models.ServicePlanFields, error) 17 GetPlansForService(string) ([]models.ServicePlanFields, error) 18 GetPlansVisibleToOrg(string) ([]models.ServicePlanFields, error) 19 } 20 21 var ( 22 OrgToPlansVisibilityMap *map[string][]string 23 PlanToOrgsVisibilityMap *map[string][]string 24 ) 25 26 type Builder struct { 27 servicePlanRepo api.ServicePlanRepository 28 servicePlanVisibilityRepo api.ServicePlanVisibilityRepository 29 orgRepo organizations.OrganizationRepository 30 } 31 32 func NewBuilder(plan api.ServicePlanRepository, vis api.ServicePlanVisibilityRepository, org organizations.OrganizationRepository) Builder { 33 return Builder{ 34 servicePlanRepo: plan, 35 servicePlanVisibilityRepo: vis, 36 orgRepo: org, 37 } 38 } 39 40 func (builder Builder) AttachOrgToPlans(plans []models.ServicePlanFields, orgName string) ([]models.ServicePlanFields, error) { 41 visMap, err := builder.buildPlanToOrgVisibilityMap(orgName) 42 if err != nil { 43 return nil, err 44 } 45 for planIndex := range plans { 46 plan := &plans[planIndex] 47 plan.OrgNames = visMap[plan.GUID] 48 } 49 50 return plans, nil 51 } 52 53 func (builder Builder) AttachOrgsToPlans(plans []models.ServicePlanFields) ([]models.ServicePlanFields, error) { 54 visMap, err := builder.buildPlanToOrgsVisibilityMap() 55 if err != nil { 56 return nil, err 57 } 58 for planIndex := range plans { 59 plan := &plans[planIndex] 60 plan.OrgNames = visMap[plan.GUID] 61 } 62 63 return plans, nil 64 } 65 66 func (builder Builder) GetPlansForServiceForOrg(serviceGUID string, orgName string) ([]models.ServicePlanFields, error) { 67 plans, err := builder.servicePlanRepo.Search(map[string]string{"service_guid": serviceGUID}) 68 if err != nil { 69 return nil, err 70 } 71 72 plans, err = builder.AttachOrgToPlans(plans, orgName) 73 if err != nil { 74 return nil, err 75 } 76 return plans, nil 77 } 78 79 func (builder Builder) GetPlansForService(serviceGUID string) ([]models.ServicePlanFields, error) { 80 plans, err := builder.servicePlanRepo.Search(map[string]string{"service_guid": serviceGUID}) 81 if err != nil { 82 return nil, err 83 } 84 return plans, nil 85 } 86 87 func (builder Builder) GetPlansForServiceWithOrgs(serviceGUID string) ([]models.ServicePlanFields, error) { 88 plans, err := builder.GetPlansForService(serviceGUID) 89 if err != nil { 90 return nil, err 91 } 92 93 plans, err = builder.AttachOrgsToPlans(plans) 94 if err != nil { 95 return nil, err 96 } 97 return plans, nil 98 } 99 100 func (builder Builder) GetPlansForManyServicesWithOrgs(serviceGUIDs []string) ([]models.ServicePlanFields, error) { 101 plans, err := builder.servicePlanRepo.ListPlansFromManyServices(serviceGUIDs) 102 if err != nil { 103 return nil, err 104 } 105 106 plans, err = builder.AttachOrgsToPlans(plans) 107 if err != nil { 108 return nil, err 109 } 110 return plans, nil 111 } 112 113 func (builder Builder) GetPlansVisibleToOrg(orgName string) ([]models.ServicePlanFields, error) { 114 var plansToReturn []models.ServicePlanFields 115 allPlans, err := builder.servicePlanRepo.Search(nil) 116 117 planToOrgsVisMap, err := builder.buildPlanToOrgsVisibilityMap() 118 if err != nil { 119 return nil, err 120 } 121 122 orgToPlansVisMap := builder.buildOrgToPlansVisibilityMap(planToOrgsVisMap) 123 124 filterOrgPlans := orgToPlansVisMap[orgName] 125 126 for _, plan := range allPlans { 127 if builder.containsGUID(filterOrgPlans, plan.GUID) { 128 plan.OrgNames = planToOrgsVisMap[plan.GUID] 129 plansToReturn = append(plansToReturn, plan) 130 } else if plan.Public { 131 plansToReturn = append(plansToReturn, plan) 132 } 133 } 134 135 return plansToReturn, nil 136 } 137 138 func (builder Builder) containsGUID(guidSlice []string, guid string) bool { 139 for _, g := range guidSlice { 140 if g == guid { 141 return true 142 } 143 } 144 return false 145 } 146 147 func (builder Builder) buildPlanToOrgVisibilityMap(orgName string) (map[string][]string, error) { 148 org, err := builder.orgRepo.FindByName(orgName) 149 if err != nil { 150 return nil, err 151 } 152 153 visibilities, err := builder.servicePlanVisibilityRepo.Search(map[string]string{"organization_guid": org.GUID}) 154 if err != nil { 155 return nil, err 156 } 157 158 visMap := make(map[string][]string) 159 for _, vis := range visibilities { 160 visMap[vis.ServicePlanGUID] = []string{org.Name} 161 } 162 163 return visMap, nil 164 } 165 166 func (builder Builder) buildPlanToOrgsVisibilityMap() (map[string][]string, error) { 167 // Since this map doesn't ever change, we memoize it for performance 168 if PlanToOrgsVisibilityMap == nil { 169 orgLookup := make(map[string]string) 170 171 visibilities, err := builder.servicePlanVisibilityRepo.List() 172 if err != nil { 173 return nil, err 174 } 175 176 orgGUIDs := builder.getUniqueOrgGUIDsFromVisibilities(visibilities) 177 178 orgs, err := builder.orgRepo.GetManyOrgsByGUID(orgGUIDs) 179 if err != nil { 180 return nil, err 181 } 182 183 for _, org := range orgs { 184 orgLookup[org.GUID] = org.Name 185 } 186 187 visMap := make(map[string][]string) 188 for _, vis := range visibilities { 189 visMap[vis.ServicePlanGUID] = append(visMap[vis.ServicePlanGUID], orgLookup[vis.OrganizationGUID]) 190 } 191 192 PlanToOrgsVisibilityMap = &visMap 193 } 194 195 return *PlanToOrgsVisibilityMap, nil 196 } 197 198 func (builder Builder) getUniqueOrgGUIDsFromVisibilities(visibilities []models.ServicePlanVisibilityFields) (orgGUIDs []string) { 199 for _, visibility := range visibilities { 200 found := false 201 for _, orgGUID := range orgGUIDs { 202 if orgGUID == visibility.OrganizationGUID { 203 found = true 204 break 205 } 206 } 207 if !found { 208 orgGUIDs = append(orgGUIDs, visibility.OrganizationGUID) 209 } 210 } 211 return 212 } 213 214 func (builder Builder) buildOrgToPlansVisibilityMap(planToOrgsMap map[string][]string) map[string][]string { 215 if OrgToPlansVisibilityMap == nil { 216 visMap := make(map[string][]string) 217 for planGUID, orgNames := range planToOrgsMap { 218 for _, orgName := range orgNames { 219 visMap[orgName] = append(visMap[orgName], planGUID) 220 } 221 } 222 OrgToPlansVisibilityMap = &visMap 223 } 224 225 return *OrgToPlansVisibilityMap 226 }