github.com/franc20/ayesa_sap@v7.0.0-beta.28.0.20200124003224-302d4d52fa6c+incompatible/actor/v7action/route.go (about)

     1  package v7action
     2  
     3  import (
     4  	"sort"
     5  	"strings"
     6  
     7  	"code.cloudfoundry.org/cli/actor/actionerror"
     8  	"code.cloudfoundry.org/cli/api/cloudcontroller/ccerror"
     9  	"code.cloudfoundry.org/cli/api/cloudcontroller/ccv3"
    10  	"code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/constant"
    11  	"code.cloudfoundry.org/cli/util/sorting"
    12  )
    13  
    14  type RouteDestination struct {
    15  	GUID string
    16  	App  RouteDestinationApp
    17  }
    18  
    19  type RouteDestinationApp ccv3.RouteDestinationApp
    20  
    21  type Route struct {
    22  	GUID         string
    23  	SpaceGUID    string
    24  	DomainGUID   string
    25  	Host         string
    26  	Path         string
    27  	DomainName   string
    28  	SpaceName    string
    29  	URL          string
    30  	Destinations []RouteDestination
    31  	Metadata     *Metadata
    32  }
    33  
    34  type RouteSummary struct {
    35  	Route
    36  	AppNames []string
    37  }
    38  
    39  func (actor Actor) CreateRoute(spaceGUID, domainName, hostname, path string) (Route, Warnings, error) {
    40  	allWarnings := Warnings{}
    41  	domain, warnings, err := actor.GetDomainByName(domainName)
    42  	allWarnings = append(allWarnings, warnings...)
    43  
    44  	if err != nil {
    45  		return Route{}, allWarnings, err
    46  	}
    47  
    48  	route, apiWarnings, err := actor.CloudControllerClient.CreateRoute(ccv3.Route{
    49  		SpaceGUID:  spaceGUID,
    50  		DomainGUID: domain.GUID,
    51  		Host:       hostname,
    52  		Path:       path,
    53  	})
    54  
    55  	actorWarnings := Warnings(apiWarnings)
    56  	allWarnings = append(allWarnings, actorWarnings...)
    57  
    58  	if _, ok := err.(ccerror.RouteNotUniqueError); ok {
    59  		return Route{}, allWarnings, actionerror.RouteAlreadyExistsError{Err: err}
    60  	}
    61  
    62  	return Route{
    63  		GUID:       route.GUID,
    64  		Host:       route.Host,
    65  		Path:       route.Path,
    66  		SpaceGUID:  route.SpaceGUID,
    67  		DomainGUID: route.DomainGUID,
    68  		SpaceName:  spaceGUID,
    69  		DomainName: domainName,
    70  	}, allWarnings, err
    71  }
    72  
    73  func (actor Actor) GetRouteDestinations(routeGUID string) ([]RouteDestination, Warnings, error) {
    74  	destinations, warnings, err := actor.CloudControllerClient.GetRouteDestinations(routeGUID)
    75  
    76  	actorDestinations := []RouteDestination{}
    77  	for _, dst := range destinations {
    78  		actorDestinations = append(actorDestinations, RouteDestination{
    79  			GUID: dst.GUID,
    80  			App:  RouteDestinationApp(dst.App),
    81  		})
    82  	}
    83  
    84  	return actorDestinations, Warnings(warnings), err
    85  }
    86  
    87  func (actor Actor) GetRouteDestinationByAppGUID(routeGUID string, appGUID string) (RouteDestination, Warnings, error) {
    88  	allDestinations, warnings, err := actor.GetRouteDestinations(routeGUID)
    89  	if err != nil {
    90  		return RouteDestination{}, warnings, err
    91  	}
    92  
    93  	for _, destination := range allDestinations {
    94  		if destination.App.GUID == appGUID && destination.App.Process.Type == constant.ProcessTypeWeb {
    95  			return destination, warnings, nil
    96  		}
    97  	}
    98  
    99  	return RouteDestination{}, warnings, actionerror.RouteDestinationNotFoundError{
   100  		AppGUID:     appGUID,
   101  		ProcessType: constant.ProcessTypeWeb,
   102  		RouteGUID:   routeGUID,
   103  	}
   104  }
   105  
   106  func (actor Actor) GetRoutesBySpace(spaceGUID string, labelSelector string) ([]Route, Warnings, error) {
   107  	allWarnings := Warnings{}
   108  	queries := []ccv3.Query{
   109  		ccv3.Query{Key: ccv3.SpaceGUIDFilter, Values: []string{spaceGUID}},
   110  	}
   111  	if len(labelSelector) > 0 {
   112  		queries = append(queries, ccv3.Query{Key: ccv3.LabelSelectorFilter, Values: []string{labelSelector}})
   113  	}
   114  
   115  	routes, warnings, err := actor.CloudControllerClient.GetRoutes(queries...)
   116  	allWarnings = append(allWarnings, warnings...)
   117  	if err != nil {
   118  		return nil, allWarnings, err
   119  	}
   120  
   121  	ret, actor_warnings, err := actor.createActionRoutes(routes, allWarnings)
   122  
   123  	return ret, actor_warnings, err
   124  }
   125  
   126  func (actor Actor) parseRoutePath(routePath string) (string, string, string, string, Warnings, error) {
   127  	var warnings Warnings
   128  	var hostPart = ""
   129  	var pathPart = ""
   130  	routeParts := strings.SplitN(routePath, "/", 2)
   131  	domainName := routeParts[0]
   132  	if len(routeParts) > 1 {
   133  		pathPart = "/" + routeParts[1]
   134  	}
   135  	domainParts := strings.SplitN(domainName, ".", 2)
   136  	domainHasMultipleParts := len(domainParts) > 1
   137  
   138  	domain, allWarnings, err := actor.GetDomainByName(domainName)
   139  
   140  	_, domainNotFound := err.(actionerror.DomainNotFoundError)
   141  
   142  	needToCheckForHost := domainNotFound && domainHasMultipleParts
   143  	if err != nil && !needToCheckForHost {
   144  		return "", "", "", "", allWarnings, err
   145  	}
   146  
   147  	if needToCheckForHost {
   148  		domainName = domainParts[1]
   149  		hostPart = domainParts[0]
   150  		domain, warnings, err = actor.GetDomainByName(domainName)
   151  		allWarnings = append(allWarnings, warnings...)
   152  		if err != nil {
   153  			return "", "", "", "", allWarnings, err
   154  		}
   155  	}
   156  
   157  	return hostPart, pathPart, domainName, domain.GUID, allWarnings, nil
   158  }
   159  
   160  func (actor Actor) GetRoute(routePath string, spaceGUID string) (Route, Warnings, error) {
   161  	filters := []ccv3.Query{
   162  		ccv3.Query{
   163  			Key:    ccv3.SpaceGUIDFilter,
   164  			Values: []string{spaceGUID},
   165  		},
   166  	}
   167  	hostPart, pathPart, domainName, domainGUID, allWarnings, err := actor.parseRoutePath(routePath)
   168  	if err != nil {
   169  		return Route{}, allWarnings, err
   170  	}
   171  	filters = append(filters, ccv3.Query{
   172  		Key:    ccv3.DomainGUIDFilter,
   173  		Values: []string{domainGUID},
   174  	})
   175  	filters = append(filters, ccv3.Query{Key: ccv3.HostsFilter,
   176  		Values: []string{hostPart},
   177  	})
   178  	filters = append(filters, ccv3.Query{Key: ccv3.PathsFilter,
   179  		Values: []string{pathPart},
   180  	})
   181  	routes, warnings, err := actor.CloudControllerClient.GetRoutes(filters...)
   182  	allWarnings = append(allWarnings, warnings...)
   183  	if err != nil {
   184  		return Route{}, allWarnings, err
   185  	}
   186  	if len(routes) == 0 {
   187  		return Route{}, allWarnings, actionerror.RouteNotFoundError{
   188  			Host:       hostPart,
   189  			DomainName: domainName,
   190  			Path:       pathPart,
   191  		}
   192  	}
   193  
   194  	actionRoutes, allWarnings, err := actor.createActionRoutes(routes, allWarnings)
   195  	if err != nil {
   196  		return Route{}, allWarnings, err
   197  	}
   198  	return actionRoutes[0], allWarnings, nil
   199  }
   200  
   201  func (actor Actor) GetRoutesByOrg(orgGUID string, labelSelector string) ([]Route, Warnings, error) {
   202  	allWarnings := Warnings{}
   203  	queries := []ccv3.Query{
   204  		ccv3.Query{Key: ccv3.OrganizationGUIDFilter, Values: []string{orgGUID}},
   205  	}
   206  	if len(labelSelector) > 0 {
   207  		queries = append(queries, ccv3.Query{Key: ccv3.LabelSelectorFilter, Values: []string{labelSelector}})
   208  	}
   209  
   210  	routes, warnings, err := actor.CloudControllerClient.GetRoutes(queries...)
   211  	allWarnings = append(allWarnings, warnings...)
   212  	if err != nil {
   213  		return nil, allWarnings, err
   214  	}
   215  
   216  	return actor.createActionRoutes(routes, allWarnings)
   217  }
   218  
   219  func (actor Actor) GetRouteSummaries(routes []Route) ([]RouteSummary, Warnings, error) {
   220  	var allWarnings Warnings
   221  	var routeSummaries []RouteSummary
   222  
   223  	destinationAppGUIDsByRouteGUID := make(map[string][]string)
   224  	destinationAppGUIDs := make(map[string]bool)
   225  	var uniqueAppGUIDs []string
   226  
   227  	for _, route := range routes {
   228  		for _, destination := range route.Destinations {
   229  			appGUID := destination.App.GUID
   230  
   231  			if _, ok := destinationAppGUIDs[appGUID]; !ok {
   232  				destinationAppGUIDs[appGUID] = true
   233  				uniqueAppGUIDs = append(uniqueAppGUIDs, appGUID)
   234  			}
   235  
   236  			destinationAppGUIDsByRouteGUID[route.GUID] = append(destinationAppGUIDsByRouteGUID[route.GUID], appGUID)
   237  		}
   238  	}
   239  
   240  	apps, warnings, err := actor.GetApplicationsByGUIDs(uniqueAppGUIDs)
   241  	allWarnings = append(allWarnings, warnings...)
   242  	if err != nil {
   243  		return nil, allWarnings, err
   244  	}
   245  
   246  	appNamesByGUID := make(map[string]string)
   247  	for _, app := range apps {
   248  		appNamesByGUID[app.GUID] = app.Name
   249  	}
   250  
   251  	for _, route := range routes {
   252  		var appNames []string
   253  
   254  		appGUIDs := destinationAppGUIDsByRouteGUID[route.GUID]
   255  		for _, appGUID := range appGUIDs {
   256  			appNames = append(appNames, appNamesByGUID[appGUID])
   257  		}
   258  
   259  		routeSummaries = append(routeSummaries, RouteSummary{
   260  			Route:    route,
   261  			AppNames: appNames,
   262  		})
   263  	}
   264  
   265  	sort.Slice(routeSummaries, func(i, j int) bool {
   266  		return sorting.LessIgnoreCase(routeSummaries[i].SpaceName, routeSummaries[j].SpaceName)
   267  	})
   268  
   269  	return routeSummaries, allWarnings, nil
   270  }
   271  
   272  func (actor Actor) DeleteOrphanedRoutes(spaceGUID string) (Warnings, error) {
   273  	var allWarnings Warnings
   274  
   275  	jobURL, warnings, err := actor.CloudControllerClient.DeleteOrphanedRoutes(spaceGUID)
   276  	allWarnings = append(allWarnings, warnings...)
   277  	if err != nil {
   278  		return allWarnings, err
   279  	}
   280  
   281  	warnings, err = actor.CloudControllerClient.PollJob(jobURL)
   282  	allWarnings = append(allWarnings, warnings...)
   283  
   284  	return allWarnings, err
   285  }
   286  
   287  func (actor Actor) DeleteRoute(domainName, hostname, path string) (Warnings, error) {
   288  	allWarnings := Warnings{}
   289  	domain, warnings, err := actor.GetDomainByName(domainName)
   290  	allWarnings = append(allWarnings, warnings...)
   291  
   292  	if _, ok := err.(actionerror.DomainNotFoundError); ok {
   293  		allWarnings = append(allWarnings, err.Error())
   294  		return allWarnings, nil
   295  	}
   296  
   297  	if err != nil {
   298  		return allWarnings, err
   299  	}
   300  
   301  	queryArray := []ccv3.Query{
   302  		{Key: ccv3.DomainGUIDFilter, Values: []string{domain.GUID}},
   303  		{Key: ccv3.HostsFilter, Values: []string{hostname}},
   304  		{Key: ccv3.PathsFilter, Values: []string{path}},
   305  	}
   306  
   307  	routes, apiWarnings, err := actor.CloudControllerClient.GetRoutes(queryArray...)
   308  
   309  	actorWarnings := Warnings(apiWarnings)
   310  	allWarnings = append(allWarnings, actorWarnings...)
   311  
   312  	if err != nil {
   313  		return allWarnings, err
   314  	}
   315  
   316  	if len(routes) == 0 {
   317  		return allWarnings, actionerror.RouteNotFoundError{
   318  			DomainName: domainName,
   319  			Host:       hostname,
   320  			Path:       path,
   321  		}
   322  	}
   323  
   324  	jobURL, apiWarnings, err := actor.CloudControllerClient.DeleteRoute(routes[0].GUID)
   325  	actorWarnings = Warnings(apiWarnings)
   326  	allWarnings = append(allWarnings, actorWarnings...)
   327  
   328  	if err != nil {
   329  		return allWarnings, err
   330  	}
   331  
   332  	pollJobWarnings, err := actor.CloudControllerClient.PollJob(jobURL)
   333  	allWarnings = append(allWarnings, Warnings(pollJobWarnings)...)
   334  
   335  	return allWarnings, err
   336  }
   337  
   338  func (actor Actor) GetRouteByAttributes(domainName string, domainGUID string, hostname string, path string) (Route, Warnings, error) {
   339  	ccRoutes, ccWarnings, err := actor.CloudControllerClient.GetRoutes(
   340  		ccv3.Query{Key: ccv3.DomainGUIDFilter, Values: []string{domainGUID}},
   341  		ccv3.Query{Key: ccv3.HostsFilter, Values: []string{hostname}},
   342  		ccv3.Query{Key: ccv3.PathsFilter, Values: []string{path}},
   343  	)
   344  
   345  	if err != nil {
   346  		return Route{}, Warnings(ccWarnings), err
   347  	}
   348  
   349  	if len(ccRoutes) < 1 {
   350  		return Route{}, Warnings(ccWarnings), actionerror.RouteNotFoundError{
   351  			DomainName: domainName,
   352  			DomainGUID: domainGUID,
   353  			Host:       hostname,
   354  			Path:       path,
   355  		}
   356  	}
   357  
   358  	return Route{
   359  		GUID:       ccRoutes[0].GUID,
   360  		Host:       ccRoutes[0].Host,
   361  		Path:       ccRoutes[0].Path,
   362  		SpaceGUID:  ccRoutes[0].SpaceGUID,
   363  		DomainGUID: ccRoutes[0].DomainGUID,
   364  	}, Warnings(ccWarnings), nil
   365  }
   366  
   367  func (actor Actor) MapRoute(routeGUID string, appGUID string) (Warnings, error) {
   368  	warnings, err := actor.CloudControllerClient.MapRoute(routeGUID, appGUID)
   369  	return Warnings(warnings), err
   370  }
   371  
   372  func (actor Actor) UnmapRoute(routeGUID string, destinationGUID string) (Warnings, error) {
   373  	warnings, err := actor.CloudControllerClient.UnmapRoute(routeGUID, destinationGUID)
   374  	return Warnings(warnings), err
   375  }
   376  
   377  func (actor Actor) GetApplicationRoutes(appGUID string) ([]Route, Warnings, error) {
   378  	allWarnings := Warnings{}
   379  
   380  	routes, warnings, err := actor.CloudControllerClient.GetApplicationRoutes(appGUID)
   381  	allWarnings = append(allWarnings, warnings...)
   382  	if err != nil {
   383  		return nil, allWarnings, err
   384  	}
   385  
   386  	if len(routes) == 0 {
   387  		return nil, allWarnings, err
   388  	}
   389  
   390  	return actor.createActionRoutes(routes, allWarnings)
   391  }
   392  
   393  func (actor Actor) createActionRoutes(routes []ccv3.Route, allWarnings Warnings) ([]Route, Warnings, error) {
   394  	spaceGUIDsSet := map[string]struct{}{}
   395  	spacesQuery := ccv3.Query{Key: ccv3.GUIDFilter, Values: []string{}}
   396  
   397  	for _, route := range routes {
   398  		if _, ok := spaceGUIDsSet[route.SpaceGUID]; !ok {
   399  			spacesQuery.Values = append(spacesQuery.Values, route.SpaceGUID)
   400  			spaceGUIDsSet[route.SpaceGUID] = struct{}{}
   401  		}
   402  	}
   403  
   404  	spaces, warnings, err := actor.CloudControllerClient.GetSpaces(spacesQuery)
   405  	allWarnings = append(allWarnings, warnings...)
   406  	if err != nil {
   407  		return nil, allWarnings, err
   408  	}
   409  
   410  	spacesByGUID := map[string]ccv3.Space{}
   411  	for _, space := range spaces {
   412  		spacesByGUID[space.GUID] = space
   413  	}
   414  
   415  	actorRoutes := []Route{}
   416  	for _, route := range routes {
   417  		destinations := make([]RouteDestination, len(route.Destinations))
   418  		for i, destination := range route.Destinations {
   419  			destinations[i] = RouteDestination{
   420  				GUID: destination.GUID,
   421  				App:  RouteDestinationApp(destination.App),
   422  			}
   423  		}
   424  
   425  		actorRoute := Route{
   426  			GUID:         route.GUID,
   427  			Host:         route.Host,
   428  			Path:         route.Path,
   429  			SpaceGUID:    route.SpaceGUID,
   430  			DomainGUID:   route.DomainGUID,
   431  			URL:          route.URL,
   432  			SpaceName:    spacesByGUID[route.SpaceGUID].Name,
   433  			DomainName:   getDomainName(route.URL, route.Host, route.Path),
   434  			Destinations: destinations,
   435  		}
   436  
   437  		if route.Metadata != nil {
   438  			metadata := Metadata(*route.Metadata)
   439  			actorRoute.Metadata = &metadata
   440  		}
   441  
   442  		actorRoutes = append(actorRoutes, actorRoute)
   443  	}
   444  
   445  	return actorRoutes, allWarnings, nil
   446  }
   447  
   448  func getDomainName(fullURL, host, path string) string {
   449  	domainWithoutHost := strings.TrimPrefix(fullURL, host+".")
   450  	return strings.TrimSuffix(domainWithoutHost, path)
   451  }