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  }