github.com/willmadison/cli@v6.40.1-0.20181018160101-29d5937903ff+incompatible/actor/pushaction/route_test.go (about)

     1  package pushaction_test
     2  
     3  import (
     4  	"errors"
     5  	"strings"
     6  
     7  	"code.cloudfoundry.org/cli/actor/actionerror"
     8  	. "code.cloudfoundry.org/cli/actor/pushaction"
     9  	"code.cloudfoundry.org/cli/actor/pushaction/pushactionfakes"
    10  	"code.cloudfoundry.org/cli/actor/v2action"
    11  	"code.cloudfoundry.org/cli/api/cloudcontroller/ccv2/constant"
    12  	"code.cloudfoundry.org/cli/util/manifest"
    13  
    14  	. "github.com/onsi/ginkgo"
    15  	. "github.com/onsi/gomega"
    16  )
    17  
    18  var _ = Describe("Routes", func() {
    19  	var (
    20  		actor                   *Actor
    21  		fakeV2Actor             *pushactionfakes.FakeV2Actor
    22  		fakeRandomWordGenerator *pushactionfakes.FakeRandomWordGenerator
    23  	)
    24  
    25  	BeforeEach(func() {
    26  		actor, fakeV2Actor, _, _ = getTestPushActor()
    27  
    28  		fakeRandomWordGenerator = new(pushactionfakes.FakeRandomWordGenerator)
    29  		actor.WordGenerator = fakeRandomWordGenerator
    30  	})
    31  
    32  	Describe("UnmapRoutes", func() {
    33  		var (
    34  			config ApplicationConfig
    35  
    36  			returnedConfig ApplicationConfig
    37  			warnings       Warnings
    38  			executeErr     error
    39  		)
    40  
    41  		BeforeEach(func() {
    42  			config = ApplicationConfig{
    43  				DesiredApplication: Application{
    44  					Application: v2action.Application{
    45  						GUID: "some-app-guid",
    46  					}},
    47  			}
    48  		})
    49  
    50  		JustBeforeEach(func() {
    51  			returnedConfig, warnings, executeErr = actor.UnmapRoutes(config)
    52  		})
    53  
    54  		When("there are routes on the application", func() {
    55  			BeforeEach(func() {
    56  				config.CurrentRoutes = []v2action.Route{
    57  					{GUID: "some-route-guid-1", Host: "some-route-1", Domain: v2action.Domain{Name: "some-domain.com"}},
    58  					{GUID: "some-route-guid-2", Host: "some-route-2"},
    59  				}
    60  			})
    61  
    62  			When("the unmapping is successful", func() {
    63  				BeforeEach(func() {
    64  					fakeV2Actor.UnmapRouteFromApplicationReturns(v2action.Warnings{"unmap-route-warning"}, nil)
    65  				})
    66  
    67  				It("only creates the routes that do not exist", func() {
    68  					Expect(executeErr).ToNot(HaveOccurred())
    69  					Expect(warnings).To(ConsistOf("unmap-route-warning", "unmap-route-warning"))
    70  
    71  					Expect(returnedConfig.CurrentRoutes).To(BeEmpty())
    72  
    73  					Expect(fakeV2Actor.UnmapRouteFromApplicationCallCount()).To(Equal(2))
    74  
    75  					routeGUID, appGUID := fakeV2Actor.UnmapRouteFromApplicationArgsForCall(0)
    76  					Expect(routeGUID).To(Equal("some-route-guid-1"))
    77  					Expect(appGUID).To(Equal("some-app-guid"))
    78  
    79  					routeGUID, appGUID = fakeV2Actor.UnmapRouteFromApplicationArgsForCall(1)
    80  					Expect(routeGUID).To(Equal("some-route-guid-2"))
    81  					Expect(appGUID).To(Equal("some-app-guid"))
    82  				})
    83  			})
    84  
    85  			When("the mapping errors", func() {
    86  				var expectedErr error
    87  				BeforeEach(func() {
    88  					expectedErr = errors.New("oh my")
    89  					fakeV2Actor.UnmapRouteFromApplicationReturns(v2action.Warnings{"unmap-route-warning"}, expectedErr)
    90  				})
    91  
    92  				It("sends the warnings and errors and returns true", func() {
    93  					Expect(executeErr).To(MatchError(expectedErr))
    94  					Expect(warnings).To(ConsistOf("unmap-route-warning"))
    95  				})
    96  			})
    97  		})
    98  	})
    99  
   100  	Describe("MapRoutes", func() {
   101  		var (
   102  			config ApplicationConfig
   103  
   104  			returnedConfig ApplicationConfig
   105  			boundRoutes    bool
   106  			warnings       Warnings
   107  			executeErr     error
   108  		)
   109  
   110  		BeforeEach(func() {
   111  			config = ApplicationConfig{
   112  				DesiredApplication: Application{
   113  					Application: v2action.Application{
   114  						GUID: "some-app-guid",
   115  					}},
   116  			}
   117  		})
   118  
   119  		JustBeforeEach(func() {
   120  			returnedConfig, boundRoutes, warnings, executeErr = actor.MapRoutes(config)
   121  		})
   122  
   123  		When("routes need to be bound to the application", func() {
   124  			BeforeEach(func() {
   125  				config.CurrentRoutes = []v2action.Route{
   126  					{GUID: "some-route-guid-2", Host: "some-route-2"},
   127  				}
   128  				config.DesiredRoutes = []v2action.Route{
   129  					{GUID: "some-route-guid-1", Host: "some-route-1", Domain: v2action.Domain{Name: "some-domain.com"}},
   130  					{GUID: "some-route-guid-2", Host: "some-route-2"},
   131  					{GUID: "some-route-guid-3", Host: "some-route-3"},
   132  				}
   133  			})
   134  
   135  			When("the mapping is successful", func() {
   136  				BeforeEach(func() {
   137  					fakeV2Actor.MapRouteToApplicationReturns(v2action.Warnings{"map-route-warning"}, nil)
   138  				})
   139  
   140  				It("only creates the routes that do not exist", func() {
   141  					Expect(executeErr).ToNot(HaveOccurred())
   142  					Expect(warnings).To(ConsistOf("map-route-warning", "map-route-warning"))
   143  					Expect(boundRoutes).To(BeTrue())
   144  
   145  					Expect(returnedConfig.CurrentRoutes).To(Equal(config.DesiredRoutes))
   146  
   147  					Expect(fakeV2Actor.MapRouteToApplicationCallCount()).To(Equal(2))
   148  
   149  					routeGUID, appGUID := fakeV2Actor.MapRouteToApplicationArgsForCall(0)
   150  					Expect(routeGUID).To(Equal("some-route-guid-1"))
   151  					Expect(appGUID).To(Equal("some-app-guid"))
   152  
   153  					routeGUID, appGUID = fakeV2Actor.MapRouteToApplicationArgsForCall(1)
   154  					Expect(routeGUID).To(Equal("some-route-guid-3"))
   155  					Expect(appGUID).To(Equal("some-app-guid"))
   156  				})
   157  			})
   158  
   159  			When("the mapping errors", func() {
   160  				When("the route is bound in another space", func() {
   161  					BeforeEach(func() {
   162  						fakeV2Actor.MapRouteToApplicationReturns(v2action.Warnings{"map-route-warning"}, actionerror.RouteInDifferentSpaceError{})
   163  					})
   164  
   165  					It("sends the RouteInDifferentSpaceError (with a guid set) and warnings and returns true", func() {
   166  						Expect(executeErr).To(MatchError(actionerror.RouteInDifferentSpaceError{Route: "some-route-1.some-domain.com"}))
   167  						Expect(warnings).To(ConsistOf("map-route-warning"))
   168  					})
   169  				})
   170  
   171  				Context("generic error", func() {
   172  					var expectedErr error
   173  					BeforeEach(func() {
   174  						expectedErr = errors.New("oh my")
   175  						fakeV2Actor.MapRouteToApplicationReturns(v2action.Warnings{"map-route-warning"}, expectedErr)
   176  					})
   177  
   178  					It("sends the warnings and errors and returns true", func() {
   179  						Expect(executeErr).To(MatchError(expectedErr))
   180  						Expect(warnings).To(ConsistOf("map-route-warning"))
   181  					})
   182  				})
   183  			})
   184  		})
   185  
   186  		When("no routes need to be bound", func() {
   187  			It("returns false", func() {
   188  				Expect(executeErr).ToNot(HaveOccurred())
   189  			})
   190  		})
   191  	})
   192  
   193  	Describe("CalculateRoutes", func() {
   194  		var (
   195  			routes         []string
   196  			orgGUID        string
   197  			spaceGUID      string
   198  			existingRoutes []v2action.Route
   199  
   200  			calculatedRoutes []v2action.Route
   201  			warnings         Warnings
   202  			executeErr       error
   203  		)
   204  
   205  		BeforeEach(func() {
   206  			routes = []string{
   207  				"a.com",
   208  				"b.a.com",
   209  				"c.b.a.com",
   210  				"d.c.b.a.com",
   211  				"a.com/some-path",
   212  				"*.f.e.com",
   213  				"*.e.com",
   214  			}
   215  			orgGUID = "some-org-guid"
   216  			spaceGUID = "some-space-guid"
   217  		})
   218  
   219  		JustBeforeEach(func() {
   220  			calculatedRoutes, warnings, executeErr = actor.CalculateRoutes(routes, orgGUID, spaceGUID, existingRoutes)
   221  		})
   222  
   223  		When("there are no known routes", func() {
   224  			BeforeEach(func() {
   225  				existingRoutes = []v2action.Route{{
   226  					GUID: "some-route-5",
   227  					Host: "banana",
   228  					Domain: v2action.Domain{
   229  						GUID: "domain-guid-1",
   230  						Name: "a.com",
   231  					},
   232  					SpaceGUID: spaceGUID,
   233  				}}
   234  			})
   235  
   236  			When("a route looking up the domains is succuessful", func() {
   237  				BeforeEach(func() {
   238  					fakeV2Actor.GetDomainsByNameAndOrganizationReturns([]v2action.Domain{
   239  						{GUID: "domain-guid-1", Name: "a.com"},
   240  						{GUID: "domain-guid-2", Name: "b.a.com"},
   241  						{GUID: "domain-guid-3", Name: "f.e.com"},
   242  						{GUID: "domain-guid-4", Name: "e.com"},
   243  					}, v2action.Warnings{"domain-warnings-1", "domains-warnings-2"}, nil)
   244  				})
   245  
   246  				When("the route is invalid", func() {
   247  					BeforeEach(func() {
   248  						routes = []string{"a.com", "b.a.com", "c.b.a.com:1234"}
   249  					})
   250  
   251  					It("returns back warnings and error", func() {
   252  						Expect(executeErr).To(MatchError(actionerror.InvalidHTTPRouteSettings{Domain: "b.a.com"}))
   253  						Expect(warnings).To(ConsistOf("domain-warnings-1", "domains-warnings-2"))
   254  					})
   255  				})
   256  
   257  				When("the route existance check is successful", func() {
   258  					BeforeEach(func() {
   259  						fakeV2Actor.FindRouteBoundToSpaceWithSettingsReturns(v2action.Route{}, v2action.Warnings{"find-route-warning"}, actionerror.RouteNotFoundError{})
   260  						fakeV2Actor.FindRouteBoundToSpaceWithSettingsReturnsOnCall(3, v2action.Route{
   261  							GUID: "route-guid-4",
   262  							Host: "d.c",
   263  							Domain: v2action.Domain{
   264  								GUID: "domain-guid-2",
   265  								Name: "b.a.com",
   266  							},
   267  							SpaceGUID: spaceGUID,
   268  						}, v2action.Warnings{"find-route-warning"}, nil)
   269  					})
   270  
   271  					It("returns new and existing routes", func() {
   272  						Expect(executeErr).NotTo(HaveOccurred())
   273  						Expect(warnings).To(ConsistOf("domain-warnings-1", "domains-warnings-2", "find-route-warning", "find-route-warning", "find-route-warning", "find-route-warning", "find-route-warning", "find-route-warning", "find-route-warning"))
   274  						Expect(calculatedRoutes).To(ConsistOf(
   275  							v2action.Route{
   276  								Domain: v2action.Domain{
   277  									GUID: "domain-guid-1",
   278  									Name: "a.com",
   279  								},
   280  								SpaceGUID: spaceGUID,
   281  							},
   282  							v2action.Route{
   283  								Domain: v2action.Domain{
   284  									GUID: "domain-guid-2",
   285  									Name: "b.a.com",
   286  								},
   287  								SpaceGUID: spaceGUID,
   288  							},
   289  							v2action.Route{
   290  								Host: "c",
   291  								Domain: v2action.Domain{
   292  									GUID: "domain-guid-2",
   293  									Name: "b.a.com",
   294  								},
   295  								SpaceGUID: spaceGUID,
   296  							},
   297  							v2action.Route{
   298  								GUID: "route-guid-4",
   299  								Host: "d.c",
   300  								Domain: v2action.Domain{
   301  									GUID: "domain-guid-2",
   302  									Name: "b.a.com",
   303  								},
   304  								SpaceGUID: spaceGUID,
   305  							},
   306  							v2action.Route{
   307  								GUID: "some-route-5",
   308  								Host: "banana",
   309  								Domain: v2action.Domain{
   310  									GUID: "domain-guid-1",
   311  									Name: "a.com",
   312  								},
   313  								SpaceGUID: spaceGUID,
   314  							},
   315  							v2action.Route{
   316  								Host: "",
   317  								Domain: v2action.Domain{
   318  									GUID: "domain-guid-1",
   319  									Name: "a.com",
   320  								},
   321  								Path:      "/some-path",
   322  								SpaceGUID: spaceGUID,
   323  							},
   324  							v2action.Route{
   325  								Host: "*",
   326  								Domain: v2action.Domain{
   327  									GUID: "domain-guid-3",
   328  									Name: "f.e.com",
   329  								},
   330  								SpaceGUID: spaceGUID,
   331  							},
   332  							v2action.Route{
   333  								Host: "*",
   334  								Domain: v2action.Domain{
   335  									GUID: "domain-guid-4",
   336  									Name: "e.com",
   337  								},
   338  								SpaceGUID: spaceGUID,
   339  							}))
   340  
   341  						Expect(fakeV2Actor.GetDomainsByNameAndOrganizationCallCount()).To(Equal(1))
   342  						domains, passedOrgGUID := fakeV2Actor.GetDomainsByNameAndOrganizationArgsForCall(0)
   343  						Expect(domains).To(ConsistOf("a.com", "b.a.com", "c.b.a.com", "d.c.b.a.com", "*.f.e.com", "f.e.com", "*.e.com", "e.com"))
   344  						Expect(passedOrgGUID).To(Equal(orgGUID))
   345  
   346  						Expect(fakeV2Actor.FindRouteBoundToSpaceWithSettingsCallCount()).To(Equal(7))
   347  						// One check is enough here - checking 4th call since it's the only
   348  						// existing one.
   349  						Expect(fakeV2Actor.FindRouteBoundToSpaceWithSettingsArgsForCall(3)).To(Equal(v2action.Route{
   350  							Host: "d.c",
   351  							Domain: v2action.Domain{
   352  								GUID: "domain-guid-2",
   353  								Name: "b.a.com",
   354  							},
   355  							SpaceGUID: spaceGUID,
   356  						}))
   357  					})
   358  				})
   359  
   360  				When("the route existance check fails", func() {
   361  					var expectedErr error
   362  
   363  					BeforeEach(func() {
   364  						expectedErr = errors.New("oh noes")
   365  						fakeV2Actor.FindRouteBoundToSpaceWithSettingsReturns(v2action.Route{}, v2action.Warnings{"find-route-warning"}, expectedErr)
   366  					})
   367  
   368  					It("returns back warnings and error", func() {
   369  						Expect(executeErr).To(MatchError(expectedErr))
   370  						Expect(warnings).To(ConsistOf("domain-warnings-1", "domains-warnings-2", "find-route-warning"))
   371  					})
   372  				})
   373  
   374  				When("one of the domains does not exist", func() {
   375  					BeforeEach(func() {
   376  						fakeV2Actor.GetDomainsByNameAndOrganizationReturns(nil, v2action.Warnings{"domain-warnings-1", "domains-warnings-2"}, nil)
   377  					})
   378  
   379  					It("returns back warnings and error", func() {
   380  						Expect(executeErr).To(MatchError(actionerror.NoMatchingDomainError{Route: "a.com"}))
   381  						Expect(warnings).To(ConsistOf("domain-warnings-1", "domains-warnings-2"))
   382  					})
   383  				})
   384  			})
   385  
   386  			When("looking up a domain returns an error", func() {
   387  				var expectedErr error
   388  
   389  				BeforeEach(func() {
   390  					expectedErr = errors.New("po-tate-toe")
   391  					fakeV2Actor.GetDomainsByNameAndOrganizationReturns(nil, v2action.Warnings{"domain-warnings-1", "domains-warnings-2"}, expectedErr)
   392  				})
   393  
   394  				It("returns back warnings and error", func() {
   395  					Expect(executeErr).To(MatchError(expectedErr))
   396  					Expect(warnings).To(ConsistOf("domain-warnings-1", "domains-warnings-2"))
   397  				})
   398  			})
   399  		})
   400  
   401  		When("there are known routes", func() {
   402  			BeforeEach(func() {
   403  				existingRoutes = []v2action.Route{{
   404  					GUID: "route-guid-4",
   405  					Host: "d.c",
   406  					Domain: v2action.Domain{
   407  						GUID: "domain-guid-2",
   408  						Name: "b.a.com",
   409  					},
   410  					SpaceGUID: spaceGUID,
   411  				}}
   412  
   413  				fakeV2Actor.GetDomainsByNameAndOrganizationReturns([]v2action.Domain{
   414  					{GUID: "domain-guid-1", Name: "a.com"},
   415  					{GUID: "domain-guid-2", Name: "b.a.com"},
   416  					{GUID: "domain-guid-3", Name: "f.e.com"},
   417  					{GUID: "domain-guid-4", Name: "e.com"},
   418  				}, v2action.Warnings{"domain-warnings-1", "domains-warnings-2"}, nil)
   419  				fakeV2Actor.FindRouteBoundToSpaceWithSettingsReturns(v2action.Route{}, v2action.Warnings{"find-route-warning"}, actionerror.RouteNotFoundError{})
   420  			})
   421  
   422  			It("does not lookup known routes", func() {
   423  				Expect(executeErr).NotTo(HaveOccurred())
   424  				Expect(warnings).To(ConsistOf("domain-warnings-1", "domains-warnings-2", "find-route-warning", "find-route-warning", "find-route-warning", "find-route-warning", "find-route-warning", "find-route-warning"))
   425  				Expect(calculatedRoutes).To(ConsistOf(
   426  					v2action.Route{
   427  						Domain: v2action.Domain{
   428  							GUID: "domain-guid-1",
   429  							Name: "a.com",
   430  						},
   431  						SpaceGUID: spaceGUID,
   432  					},
   433  					v2action.Route{
   434  						Domain: v2action.Domain{
   435  							GUID: "domain-guid-2",
   436  							Name: "b.a.com",
   437  						},
   438  						SpaceGUID: spaceGUID,
   439  					},
   440  					v2action.Route{
   441  						Host: "c",
   442  						Domain: v2action.Domain{
   443  							GUID: "domain-guid-2",
   444  							Name: "b.a.com",
   445  						},
   446  						SpaceGUID: spaceGUID,
   447  					},
   448  					v2action.Route{
   449  						GUID: "route-guid-4",
   450  						Host: "d.c",
   451  						Domain: v2action.Domain{
   452  							GUID: "domain-guid-2",
   453  							Name: "b.a.com",
   454  						},
   455  						SpaceGUID: spaceGUID,
   456  					},
   457  					v2action.Route{
   458  						Host: "",
   459  						Domain: v2action.Domain{
   460  							GUID: "domain-guid-1",
   461  							Name: "a.com",
   462  						},
   463  						Path:      "/some-path",
   464  						SpaceGUID: spaceGUID,
   465  					},
   466  					v2action.Route{
   467  						Host: "*",
   468  						Domain: v2action.Domain{
   469  							GUID: "domain-guid-3",
   470  							Name: "f.e.com",
   471  						},
   472  						SpaceGUID: spaceGUID,
   473  					},
   474  					v2action.Route{
   475  						Host: "*",
   476  						Domain: v2action.Domain{
   477  							GUID: "domain-guid-4",
   478  							Name: "e.com",
   479  						},
   480  						SpaceGUID: spaceGUID,
   481  					}))
   482  
   483  				Expect(fakeV2Actor.GetDomainsByNameAndOrganizationCallCount()).To(Equal(1))
   484  				domains, passedOrgGUID := fakeV2Actor.GetDomainsByNameAndOrganizationArgsForCall(0)
   485  				Expect(domains).To(ConsistOf("a.com", "b.a.com", "c.b.a.com", "*.f.e.com", "f.e.com", "*.e.com", "e.com"))
   486  				Expect(passedOrgGUID).To(Equal(orgGUID))
   487  			})
   488  		})
   489  	})
   490  
   491  	Describe("CreateAndMapDefaultApplicationRoute", func() {
   492  		var (
   493  			warnings   Warnings
   494  			executeErr error
   495  		)
   496  
   497  		JustBeforeEach(func() {
   498  			warnings, executeErr = actor.CreateAndMapDefaultApplicationRoute("some-org-guid", "some-space-guid",
   499  				v2action.Application{Name: "some-app", GUID: "some-app-guid"})
   500  		})
   501  
   502  		When("getting organization domains errors", func() {
   503  			BeforeEach(func() {
   504  				fakeV2Actor.GetOrganizationDomainsReturns(
   505  					[]v2action.Domain{},
   506  					v2action.Warnings{"domain-warning"},
   507  					errors.New("some-error"))
   508  			})
   509  
   510  			It("returns the error", func() {
   511  				Expect(executeErr).To(MatchError("some-error"))
   512  				Expect(warnings).To(ConsistOf("domain-warning"))
   513  			})
   514  		})
   515  
   516  		When("getting organization domains succeeds", func() {
   517  			BeforeEach(func() {
   518  				fakeV2Actor.GetOrganizationDomainsReturns(
   519  					[]v2action.Domain{
   520  						{
   521  							GUID: "some-domain-guid",
   522  							Name: "some-domain",
   523  						},
   524  					},
   525  					v2action.Warnings{"domain-warning"},
   526  					nil,
   527  				)
   528  			})
   529  
   530  			When("getting the application routes errors", func() {
   531  				BeforeEach(func() {
   532  					fakeV2Actor.GetApplicationRoutesReturns(
   533  						[]v2action.Route{},
   534  						v2action.Warnings{"route-warning"},
   535  						errors.New("some-error"),
   536  					)
   537  				})
   538  
   539  				It("returns the error", func() {
   540  					Expect(executeErr).To(MatchError("some-error"))
   541  					Expect(warnings).To(ConsistOf("domain-warning", "route-warning"))
   542  				})
   543  			})
   544  
   545  			When("getting the application routes succeeds", func() {
   546  				// TODO: do we need this context
   547  				When("the route is already bound to the app", func() {
   548  					BeforeEach(func() {
   549  						fakeV2Actor.GetApplicationRoutesReturns(
   550  							[]v2action.Route{
   551  								{
   552  									Host: "some-app",
   553  									Domain: v2action.Domain{
   554  										GUID: "some-domain-guid",
   555  										Name: "some-domain",
   556  									},
   557  									GUID:      "some-route-guid",
   558  									SpaceGUID: "some-space-guid",
   559  								},
   560  							},
   561  							v2action.Warnings{"route-warning"},
   562  							nil,
   563  						)
   564  					})
   565  
   566  					It("returns any warnings", func() {
   567  						Expect(executeErr).ToNot(HaveOccurred())
   568  						Expect(warnings).To(ConsistOf("domain-warning", "route-warning"))
   569  
   570  						Expect(fakeV2Actor.GetOrganizationDomainsCallCount()).To(Equal(1), "Expected GetOrganizationDomains to be called once, but it was not")
   571  						orgGUID := fakeV2Actor.GetOrganizationDomainsArgsForCall(0)
   572  						Expect(orgGUID).To(Equal("some-org-guid"))
   573  
   574  						Expect(fakeV2Actor.GetApplicationRoutesCallCount()).To(Equal(1), "Expected GetApplicationRoutes to be called once, but it was not")
   575  						appGUID := fakeV2Actor.GetApplicationRoutesArgsForCall(0)
   576  						Expect(appGUID).To(Equal("some-app-guid"))
   577  
   578  						Expect(fakeV2Actor.CreateRouteCallCount()).To(Equal(0), "Expected CreateRoute to not be called but it was")
   579  						Expect(fakeV2Actor.MapRouteToApplicationCallCount()).To(Equal(0), "Expected MapRouteToApplication to not be called but it was")
   580  					})
   581  				})
   582  
   583  				When("the route isn't bound to the app", func() {
   584  					When("finding route in space errors", func() {
   585  						BeforeEach(func() {
   586  							fakeV2Actor.FindRouteBoundToSpaceWithSettingsReturns(
   587  								v2action.Route{},
   588  								v2action.Warnings{"route-warning"},
   589  								errors.New("some-error"),
   590  							)
   591  						})
   592  
   593  						It("returns the error", func() {
   594  							Expect(executeErr).To(MatchError("some-error"))
   595  							Expect(warnings).To(ConsistOf("domain-warning", "route-warning"))
   596  						})
   597  					})
   598  
   599  					When("the route exists", func() {
   600  						BeforeEach(func() {
   601  							fakeV2Actor.FindRouteBoundToSpaceWithSettingsReturns(
   602  								v2action.Route{
   603  									GUID: "some-route-guid",
   604  									Host: "some-app",
   605  									Domain: v2action.Domain{
   606  										Name: "some-domain",
   607  										GUID: "some-domain-guid",
   608  									},
   609  									SpaceGUID: "some-space-guid",
   610  								},
   611  								v2action.Warnings{"route-warning"},
   612  								nil,
   613  							)
   614  						})
   615  
   616  						When("the map command returns an error", func() {
   617  							BeforeEach(func() {
   618  								fakeV2Actor.MapRouteToApplicationReturns(
   619  									v2action.Warnings{"map-warning"},
   620  									errors.New("some-error"),
   621  								)
   622  							})
   623  
   624  							It("returns the error", func() {
   625  								Expect(executeErr).To(MatchError("some-error"))
   626  								Expect(warnings).To(ConsistOf("domain-warning", "route-warning", "map-warning"))
   627  							})
   628  						})
   629  
   630  						When("the map command succeeds", func() {
   631  							BeforeEach(func() {
   632  								fakeV2Actor.MapRouteToApplicationReturns(
   633  									v2action.Warnings{"map-warning"},
   634  									nil,
   635  								)
   636  							})
   637  
   638  							It("maps the route to the app and returns any warnings", func() {
   639  								Expect(executeErr).ToNot(HaveOccurred())
   640  								Expect(warnings).To(ConsistOf("domain-warning", "route-warning", "map-warning"))
   641  
   642  								Expect(fakeV2Actor.FindRouteBoundToSpaceWithSettingsCallCount()).To(Equal(1), "Expected FindRouteBoundToSpaceWithSettings to be called once, but it was not")
   643  								spaceRoute := fakeV2Actor.FindRouteBoundToSpaceWithSettingsArgsForCall(0)
   644  								Expect(spaceRoute).To(Equal(v2action.Route{
   645  									Host: "some-app",
   646  									Domain: v2action.Domain{
   647  										Name: "some-domain",
   648  										GUID: "some-domain-guid",
   649  									},
   650  									SpaceGUID: "some-space-guid",
   651  								}))
   652  
   653  								Expect(fakeV2Actor.MapRouteToApplicationCallCount()).To(Equal(1), "Expected MapRouteToApplication to be called once, but it was not")
   654  								routeGUID, appGUID := fakeV2Actor.MapRouteToApplicationArgsForCall(0)
   655  								Expect(routeGUID).To(Equal("some-route-guid"))
   656  								Expect(appGUID).To(Equal("some-app-guid"))
   657  							})
   658  						})
   659  					})
   660  
   661  					When("the route does not exist", func() {
   662  						BeforeEach(func() {
   663  							fakeV2Actor.FindRouteBoundToSpaceWithSettingsReturns(
   664  								v2action.Route{},
   665  								v2action.Warnings{"route-warning"},
   666  								actionerror.RouteNotFoundError{},
   667  							)
   668  						})
   669  
   670  						When("the create route command errors", func() {
   671  							BeforeEach(func() {
   672  								fakeV2Actor.CreateRouteReturns(
   673  									v2action.Route{},
   674  									v2action.Warnings{"route-create-warning"},
   675  									errors.New("some-error"),
   676  								)
   677  							})
   678  
   679  							It("returns the error", func() {
   680  								Expect(executeErr).To(MatchError("some-error"))
   681  								Expect(warnings).To(ConsistOf("domain-warning", "route-warning", "route-create-warning"))
   682  							})
   683  						})
   684  
   685  						When("the create route command succeeds", func() {
   686  							BeforeEach(func() {
   687  								fakeV2Actor.CreateRouteReturns(
   688  									v2action.Route{
   689  										GUID: "some-route-guid",
   690  										Host: "some-app",
   691  										Domain: v2action.Domain{
   692  											Name: "some-domain",
   693  											GUID: "some-domain-guid",
   694  										},
   695  										SpaceGUID: "some-space-guid",
   696  									},
   697  									v2action.Warnings{"route-create-warning"},
   698  									nil,
   699  								)
   700  							})
   701  
   702  							When("the map command errors", func() {
   703  								BeforeEach(func() {
   704  									fakeV2Actor.MapRouteToApplicationReturns(
   705  										v2action.Warnings{"map-warning"},
   706  										errors.New("some-error"),
   707  									)
   708  								})
   709  
   710  								It("returns the error", func() {
   711  									Expect(executeErr).To(MatchError("some-error"))
   712  									Expect(warnings).To(ConsistOf("domain-warning", "route-warning", "route-create-warning", "map-warning"))
   713  								})
   714  							})
   715  							When("the map command succeeds", func() {
   716  
   717  								BeforeEach(func() {
   718  									fakeV2Actor.MapRouteToApplicationReturns(
   719  										v2action.Warnings{"map-warning"},
   720  										nil,
   721  									)
   722  								})
   723  
   724  								It("creates the route, maps it to the app, and returns any warnings", func() {
   725  									Expect(executeErr).ToNot(HaveOccurred())
   726  									Expect(warnings).To(ConsistOf("domain-warning", "route-warning", "route-create-warning", "map-warning"))
   727  
   728  									Expect(fakeV2Actor.CreateRouteCallCount()).To(Equal(1), "Expected CreateRoute to be called once, but it was not")
   729  									defaultRoute, shouldGeneratePort := fakeV2Actor.CreateRouteArgsForCall(0)
   730  									Expect(defaultRoute).To(Equal(v2action.Route{
   731  										Host: "some-app",
   732  										Domain: v2action.Domain{
   733  											Name: "some-domain",
   734  											GUID: "some-domain-guid",
   735  										},
   736  										SpaceGUID: "some-space-guid",
   737  									}))
   738  									Expect(shouldGeneratePort).To(BeFalse())
   739  
   740  									Expect(fakeV2Actor.FindRouteBoundToSpaceWithSettingsCallCount()).To(Equal(1), "Expected FindRouteBoundToSpaceWithSettings to be called once, but it was not")
   741  									spaceRoute := fakeV2Actor.FindRouteBoundToSpaceWithSettingsArgsForCall(0)
   742  									Expect(spaceRoute).To(Equal(v2action.Route{
   743  										Host: "some-app",
   744  										Domain: v2action.Domain{
   745  											Name: "some-domain",
   746  											GUID: "some-domain-guid",
   747  										},
   748  										SpaceGUID: "some-space-guid",
   749  									}))
   750  
   751  									Expect(fakeV2Actor.MapRouteToApplicationCallCount()).To(Equal(1), "Expected MapRouteToApplication to be called once, but it was not")
   752  									routeGUID, appGUID := fakeV2Actor.MapRouteToApplicationArgsForCall(0)
   753  									Expect(routeGUID).To(Equal("some-route-guid"))
   754  									Expect(appGUID).To(Equal("some-app-guid"))
   755  								})
   756  							})
   757  						})
   758  					})
   759  				})
   760  			})
   761  		})
   762  	})
   763  
   764  	Describe("CreateRoutes", func() {
   765  		var (
   766  			config ApplicationConfig
   767  
   768  			returnedConfig ApplicationConfig
   769  			createdRoutes  bool
   770  			warnings       Warnings
   771  			executeErr     error
   772  		)
   773  
   774  		BeforeEach(func() {
   775  			config = ApplicationConfig{}
   776  		})
   777  
   778  		JustBeforeEach(func() {
   779  			returnedConfig, createdRoutes, warnings, executeErr = actor.CreateRoutes(config)
   780  		})
   781  
   782  		Describe("when routes need to be created", func() {
   783  			BeforeEach(func() {
   784  				config.DesiredRoutes = []v2action.Route{
   785  					{GUID: "", Host: "some-route-1"},
   786  					{GUID: "some-route-guid-2", Host: "some-route-2"},
   787  					{GUID: "", Host: "some-route-3"},
   788  					{GUID: "", Host: "", Domain: v2action.Domain{RouterGroupType: constant.TCPRouterGroup}},
   789  				}
   790  			})
   791  
   792  			When("the creation is successful", func() {
   793  				BeforeEach(func() {
   794  					fakeV2Actor.CreateRouteReturnsOnCall(0, v2action.Route{GUID: "some-route-guid-1", Host: "some-route-1"}, v2action.Warnings{"create-route-warning"}, nil)
   795  					fakeV2Actor.CreateRouteReturnsOnCall(1, v2action.Route{GUID: "some-route-guid-3", Host: "some-route-3"}, v2action.Warnings{"create-route-warning"}, nil)
   796  					fakeV2Actor.CreateRouteReturnsOnCall(2, v2action.Route{GUID: "some-route-guid-4", Domain: v2action.Domain{RouterGroupType: constant.TCPRouterGroup}}, v2action.Warnings{"create-route-warning"}, nil)
   797  				})
   798  
   799  				It("only creates the routes that do not exist", func() {
   800  					Expect(executeErr).ToNot(HaveOccurred())
   801  					Expect(warnings).To(ConsistOf("create-route-warning", "create-route-warning", "create-route-warning"))
   802  					Expect(createdRoutes).To(BeTrue())
   803  					Expect(returnedConfig.DesiredRoutes).To(Equal([]v2action.Route{
   804  						{GUID: "some-route-guid-1", Host: "some-route-1"},
   805  						{GUID: "some-route-guid-2", Host: "some-route-2"},
   806  						{GUID: "some-route-guid-3", Host: "some-route-3"},
   807  						{GUID: "some-route-guid-4", Domain: v2action.Domain{RouterGroupType: constant.TCPRouterGroup}},
   808  					}))
   809  
   810  					Expect(fakeV2Actor.CreateRouteCallCount()).To(Equal(3))
   811  
   812  					passedRoute, randomRoute := fakeV2Actor.CreateRouteArgsForCall(0)
   813  					Expect(passedRoute).To(Equal(v2action.Route{Host: "some-route-1"}))
   814  					Expect(randomRoute).To(BeFalse())
   815  
   816  					passedRoute, randomRoute = fakeV2Actor.CreateRouteArgsForCall(1)
   817  					Expect(passedRoute).To(Equal(v2action.Route{Host: "some-route-3"}))
   818  					Expect(randomRoute).To(BeFalse())
   819  
   820  					passedRoute, randomRoute = fakeV2Actor.CreateRouteArgsForCall(2)
   821  					Expect(passedRoute).To(Equal(v2action.Route{GUID: "", Host: "", Domain: v2action.Domain{RouterGroupType: constant.TCPRouterGroup}}))
   822  					Expect(randomRoute).To(BeTrue())
   823  				})
   824  			})
   825  
   826  			When("the creation errors", func() {
   827  				var expectedErr error
   828  
   829  				BeforeEach(func() {
   830  					expectedErr = errors.New("oh my")
   831  					fakeV2Actor.CreateRouteReturns(
   832  						v2action.Route{},
   833  						v2action.Warnings{"create-route-warning"},
   834  						expectedErr)
   835  				})
   836  
   837  				It("sends the warnings and errors and returns true", func() {
   838  					Expect(executeErr).To(MatchError(expectedErr))
   839  					Expect(warnings).To(ConsistOf("create-route-warning"))
   840  				})
   841  			})
   842  		})
   843  
   844  		When("no routes are created", func() {
   845  			BeforeEach(func() {
   846  				config.DesiredRoutes = []v2action.Route{
   847  					{GUID: "some-route-guid-1", Host: "some-route-1"},
   848  					{GUID: "some-route-guid-2", Host: "some-route-2"},
   849  					{GUID: "some-route-guid-3", Host: "some-route-3"},
   850  				}
   851  			})
   852  
   853  			It("returns false", func() {
   854  				Expect(createdRoutes).To(BeFalse())
   855  			})
   856  		})
   857  	})
   858  
   859  	Describe("GenerateRandomRoute", func() {
   860  		var (
   861  			spaceGUID string
   862  			orgGUID   string
   863  
   864  			randomRoute v2action.Route
   865  			warnings    Warnings
   866  			executeErr  error
   867  
   868  			domain      v2action.Domain
   869  			manifestApp manifest.Application
   870  		)
   871  
   872  		BeforeEach(func() {
   873  			manifestApp = manifest.Application{
   874  				Name: "some a$pp nAme",
   875  			}
   876  			spaceGUID = "some-space-guid"
   877  			orgGUID = "some-org-guid"
   878  			domain = v2action.Domain{}
   879  		})
   880  
   881  		JustBeforeEach(func() {
   882  			randomRoute, warnings, executeErr = actor.GenerateRandomRoute(manifestApp, spaceGUID, orgGUID)
   883  		})
   884  
   885  		When("a domain is specified", func() {
   886  			BeforeEach(func() {
   887  				manifestApp.Domain = "some-domain"
   888  				domain.Name = "some-domain"
   889  				fakeRandomWordGenerator.RandomAdjectiveReturns("striped")
   890  				fakeRandomWordGenerator.RandomNounReturns("apple")
   891  
   892  				fakeV2Actor.GetDomainsByNameAndOrganizationReturns(
   893  					[]v2action.Domain{domain},
   894  					v2action.Warnings{"some-organization-domain-warning"},
   895  					nil,
   896  				)
   897  			})
   898  
   899  			It("uses the specified domain to generate a route", func() {
   900  				Expect(executeErr).ToNot(HaveOccurred())
   901  				Expect(randomRoute).To(Equal(v2action.Route{
   902  					Domain:    domain,
   903  					Host:      "some-app-name-striped-apple",
   904  					SpaceGUID: spaceGUID,
   905  				}))
   906  				Expect(warnings).To(ConsistOf("some-organization-domain-warning"))
   907  
   908  				Expect(fakeV2Actor.GetDomainsByNameAndOrganizationCallCount()).To(Equal(1))
   909  				domainsArg, orgGUIDArg := fakeV2Actor.GetDomainsByNameAndOrganizationArgsForCall(0)
   910  				Expect(domainsArg).To(ConsistOf("some-domain"))
   911  				Expect(orgGUIDArg).To(Equal("some-org-guid"))
   912  			})
   913  		})
   914  
   915  		When("no domain is specified", func() {
   916  			When("the default domain is a tcp domain", func() {
   917  				BeforeEach(func() {
   918  					domain.RouterGroupType = constant.TCPRouterGroup
   919  					fakeV2Actor.GetOrganizationDomainsReturns(
   920  						[]v2action.Domain{domain},
   921  						v2action.Warnings{"some-organization-domain-warning"},
   922  						nil,
   923  					)
   924  				})
   925  
   926  				It("generates a route with a randomly generated server side port number", func() {
   927  					Expect(executeErr).ToNot(HaveOccurred())
   928  					Expect(randomRoute).To(Equal(v2action.Route{
   929  						Domain:    domain,
   930  						SpaceGUID: spaceGUID,
   931  					}))
   932  					Expect(warnings).To(ConsistOf("some-organization-domain-warning"))
   933  
   934  					Expect(fakeV2Actor.GetOrganizationDomainsCallCount()).To(Equal(1))
   935  					Expect(fakeV2Actor.GetOrganizationDomainsArgsForCall(0)).To(Equal(orgGUID))
   936  				})
   937  			})
   938  
   939  			When("the default domain is an http domain", func() {
   940  				BeforeEach(func() {
   941  					domain.RouterGroupType = constant.HTTPRouterGroup
   942  					fakeV2Actor.GetOrganizationDomainsReturns(
   943  						[]v2action.Domain{domain},
   944  						v2action.Warnings{"some-organization-domain-warning"},
   945  						nil,
   946  					)
   947  					fakeRandomWordGenerator.RandomAdjectiveReturns("striped")
   948  					fakeRandomWordGenerator.RandomNounReturns("apple")
   949  				})
   950  
   951  				When("the app name is partially sanitized", func() {
   952  					BeforeEach(func() {
   953  						manifestApp.Name = "a--b"
   954  					})
   955  
   956  					It("generates a route whose hostname is a sanitized app name and two randomly generated words", func() {
   957  						Expect(executeErr).ToNot(HaveOccurred())
   958  						Expect(randomRoute).To(Equal(v2action.Route{
   959  							Domain:    domain,
   960  							SpaceGUID: spaceGUID,
   961  							Host:      "a--b-striped-apple",
   962  						}))
   963  						Expect(warnings).To(ConsistOf("some-organization-domain-warning"))
   964  					})
   965  				})
   966  
   967  				When("the app name is fully sanitized", func() {
   968  					BeforeEach(func() {
   969  						manifestApp.Name = "@@@"
   970  					})
   971  
   972  					It("generates a route whose hostname is a sanitized app name and two randomly generated words", func() {
   973  						Expect(executeErr).ToNot(HaveOccurred())
   974  						Expect(randomRoute).To(Equal(v2action.Route{
   975  							Domain:    domain,
   976  							SpaceGUID: spaceGUID,
   977  							Host:      "striped-apple",
   978  						}))
   979  						Expect(warnings).To(ConsistOf("some-organization-domain-warning"))
   980  					})
   981  				})
   982  			})
   983  
   984  			When("the default domain lookup fails", func() {
   985  				BeforeEach(func() {
   986  					fakeV2Actor.GetOrganizationDomainsReturns(
   987  						[]v2action.Domain{domain},
   988  						v2action.Warnings{"some-organization-domain-warning"},
   989  						errors.New("some-error"),
   990  					)
   991  				})
   992  				It("returns an error and a warning", func() {
   993  					Expect(executeErr).To(MatchError("some-error"))
   994  					Expect(warnings).To(ConsistOf("some-organization-domain-warning"))
   995  				})
   996  			})
   997  		})
   998  	})
   999  
  1000  	Describe("GetGeneratedRoute", func() {
  1001  		var (
  1002  			providedManifest manifest.Application
  1003  			orgGUID          string
  1004  			spaceGUID        string
  1005  			knownRoutes      []v2action.Route
  1006  
  1007  			defaultRoute v2action.Route
  1008  			warnings     Warnings
  1009  			executeErr   error
  1010  
  1011  			domain v2action.Domain
  1012  		)
  1013  
  1014  		BeforeEach(func() {
  1015  			providedManifest = manifest.Application{
  1016  				Name: "Some-App",
  1017  			}
  1018  			orgGUID = "some-org-guid"
  1019  			spaceGUID = "some-space-guid"
  1020  			knownRoutes = nil
  1021  
  1022  			domain = v2action.Domain{
  1023  				Name: "shared-domain.com",
  1024  				GUID: "some-shared-domain-guid",
  1025  			}
  1026  		})
  1027  
  1028  		JustBeforeEach(func() {
  1029  			defaultRoute, warnings, executeErr = actor.GetGeneratedRoute(providedManifest, orgGUID, spaceGUID, knownRoutes)
  1030  		})
  1031  
  1032  		Context("the domain is provided", func() {
  1033  			BeforeEach(func() {
  1034  				providedManifest.Domain = "shared-domain.com"
  1035  			})
  1036  
  1037  			When("the provided domain exists", func() {
  1038  				BeforeEach(func() {
  1039  					domain.Type = constant.SharedDomain
  1040  
  1041  					// Assumes new route
  1042  					fakeV2Actor.FindRouteBoundToSpaceWithSettingsReturns(v2action.Route{}, v2action.Warnings{"get-route-warnings"}, actionerror.RouteNotFoundError{})
  1043  				})
  1044  
  1045  				When("the provided domain is an HTTP domain", func() {
  1046  					BeforeEach(func() {
  1047  						fakeV2Actor.GetDomainsByNameAndOrganizationReturns(
  1048  							[]v2action.Domain{domain},
  1049  							v2action.Warnings{"some-organization-domain-warning"},
  1050  							nil,
  1051  						)
  1052  					})
  1053  
  1054  					It("it uses the provided domain instead of the first shared domain", func() {
  1055  						Expect(executeErr).ToNot(HaveOccurred())
  1056  						Expect(warnings).To(ConsistOf("some-organization-domain-warning", "get-route-warnings"))
  1057  						Expect(defaultRoute).To(Equal(v2action.Route{
  1058  							Domain:    domain,
  1059  							Host:      strings.ToLower(providedManifest.Name),
  1060  							SpaceGUID: spaceGUID,
  1061  						}))
  1062  
  1063  						Expect(fakeV2Actor.GetDomainsByNameAndOrganizationCallCount()).To(Equal(1))
  1064  						domainNamesArg, orgGUIDArg := fakeV2Actor.GetDomainsByNameAndOrganizationArgsForCall(0)
  1065  						Expect(domainNamesArg).To(Equal([]string{"shared-domain.com"}))
  1066  						Expect(orgGUIDArg).To(Equal(orgGUID))
  1067  
  1068  						Expect(fakeV2Actor.FindRouteBoundToSpaceWithSettingsCallCount()).To(Equal(1))
  1069  						Expect(fakeV2Actor.FindRouteBoundToSpaceWithSettingsArgsForCall(0)).To(Equal(v2action.Route{
  1070  							Domain:    domain,
  1071  							Host:      strings.ToLower(providedManifest.Name),
  1072  							SpaceGUID: spaceGUID,
  1073  						}))
  1074  					})
  1075  				})
  1076  
  1077  				When("the provided domain is an TCP domain", func() {
  1078  					BeforeEach(func() {
  1079  						domain.RouterGroupType = constant.TCPRouterGroup
  1080  
  1081  						fakeV2Actor.GetDomainsByNameAndOrganizationReturns(
  1082  							[]v2action.Domain{domain},
  1083  							v2action.Warnings{"some-organization-domain-warning"},
  1084  							nil,
  1085  						)
  1086  					})
  1087  
  1088  					It("it uses the provided domain instead of the first shared domain and has no host", func() {
  1089  						Expect(executeErr).ToNot(HaveOccurred())
  1090  						Expect(warnings).To(ConsistOf("some-organization-domain-warning"))
  1091  						Expect(defaultRoute).To(Equal(v2action.Route{
  1092  							Domain:    domain,
  1093  							SpaceGUID: spaceGUID,
  1094  						}))
  1095  
  1096  						Expect(fakeV2Actor.GetDomainsByNameAndOrganizationCallCount()).To(Equal(1))
  1097  						domainNamesArg, orgGUIDArg := fakeV2Actor.GetDomainsByNameAndOrganizationArgsForCall(0)
  1098  						Expect(domainNamesArg).To(Equal([]string{"shared-domain.com"}))
  1099  						Expect(orgGUIDArg).To(Equal(orgGUID))
  1100  
  1101  						Expect(fakeV2Actor.FindRouteBoundToSpaceWithSettingsCallCount()).To(Equal(0))
  1102  					})
  1103  				})
  1104  			})
  1105  
  1106  			When("the provided domain does not exist", func() {
  1107  				BeforeEach(func() {
  1108  					fakeV2Actor.GetDomainsByNameAndOrganizationReturns(
  1109  						[]v2action.Domain{},
  1110  						v2action.Warnings{"some-organization-domain-warning"},
  1111  						nil,
  1112  					)
  1113  				})
  1114  
  1115  				It("returns an DomainNotFoundError", func() {
  1116  					Expect(executeErr).To(MatchError(actionerror.DomainNotFoundError{Name: "shared-domain.com"}))
  1117  					Expect(warnings).To(ConsistOf("some-organization-domain-warning"))
  1118  				})
  1119  			})
  1120  		})
  1121  
  1122  		Context("the hostname is provided", func() {
  1123  			BeforeEach(func() {
  1124  				providedManifest.Hostname = "some HO_ST"
  1125  			})
  1126  
  1127  			When("the domain is an HTTP domain", func() {
  1128  				BeforeEach(func() {
  1129  					domain.Type = constant.SharedDomain
  1130  					fakeV2Actor.GetOrganizationDomainsReturns(
  1131  						[]v2action.Domain{domain},
  1132  						v2action.Warnings{"some-organization-domain-warning"},
  1133  						nil,
  1134  					)
  1135  
  1136  					// Assumes new route
  1137  					fakeV2Actor.FindRouteBoundToSpaceWithSettingsReturns(v2action.Route{}, v2action.Warnings{"get-route-warnings"}, actionerror.RouteNotFoundError{})
  1138  				})
  1139  
  1140  				It("it uses the provided hostname instead of the app name", func() {
  1141  					Expect(executeErr).ToNot(HaveOccurred())
  1142  					Expect(warnings).To(ConsistOf("some-organization-domain-warning", "get-route-warnings"))
  1143  					Expect(defaultRoute).To(Equal(v2action.Route{
  1144  						Domain:    domain,
  1145  						Host:      "some-host",
  1146  						SpaceGUID: spaceGUID,
  1147  					}))
  1148  
  1149  					Expect(fakeV2Actor.FindRouteBoundToSpaceWithSettingsCallCount()).To(Equal(1))
  1150  					Expect(fakeV2Actor.FindRouteBoundToSpaceWithSettingsArgsForCall(0)).To(Equal(v2action.Route{
  1151  						Domain:    domain,
  1152  						Host:      "some-host",
  1153  						SpaceGUID: spaceGUID,
  1154  					}))
  1155  				})
  1156  			})
  1157  
  1158  			When("the provided domain is an TCP domain", func() {
  1159  				BeforeEach(func() {
  1160  					domain.RouterGroupType = constant.TCPRouterGroup
  1161  					fakeV2Actor.GetOrganizationDomainsReturns(
  1162  						[]v2action.Domain{domain},
  1163  						v2action.Warnings{"some-organization-domain-warning"},
  1164  						nil,
  1165  					)
  1166  				})
  1167  
  1168  				It("returns an error", func() {
  1169  					Expect(executeErr).To(MatchError(actionerror.HostnameWithTCPDomainError{}))
  1170  					Expect(warnings).To(ConsistOf("some-organization-domain-warning"))
  1171  				})
  1172  			})
  1173  		})
  1174  
  1175  		When("no hostname is requested", func() {
  1176  			BeforeEach(func() {
  1177  				providedManifest.NoHostname = true
  1178  
  1179  				// Assumes new route
  1180  				fakeV2Actor.FindRouteBoundToSpaceWithSettingsReturns(v2action.Route{}, v2action.Warnings{"get-route-warnings"}, actionerror.RouteNotFoundError{})
  1181  			})
  1182  
  1183  			Context("the domain is a private domain", func() {
  1184  				BeforeEach(func() {
  1185  					domain.Type = constant.PrivateDomain
  1186  					fakeV2Actor.GetOrganizationDomainsReturns([]v2action.Domain{domain}, nil, nil)
  1187  				})
  1188  
  1189  				It("does not set the hostname for the route", func() {
  1190  					Expect(executeErr).ToNot(HaveOccurred())
  1191  					Expect(defaultRoute).To(Equal(v2action.Route{
  1192  						Domain:    domain,
  1193  						SpaceGUID: spaceGUID,
  1194  					}))
  1195  
  1196  					Expect(fakeV2Actor.FindRouteBoundToSpaceWithSettingsCallCount()).To(Equal(1))
  1197  					Expect(fakeV2Actor.FindRouteBoundToSpaceWithSettingsArgsForCall(0)).To(Equal(v2action.Route{
  1198  						Domain:    domain,
  1199  						SpaceGUID: spaceGUID,
  1200  					}))
  1201  				})
  1202  			})
  1203  
  1204  			Context("the domain is a shared domain", func() {
  1205  				When("the domain is a TCP Domain", func() {
  1206  					BeforeEach(func() {
  1207  						domain.Type = constant.SharedDomain
  1208  						domain.RouterGroupType = constant.TCPRouterGroup
  1209  						fakeV2Actor.GetOrganizationDomainsReturns([]v2action.Domain{domain}, v2action.Warnings{"private-domain-warnings", "shared-domain-warnings"}, nil)
  1210  					})
  1211  
  1212  					It("returns a TCP route", func() {
  1213  						Expect(executeErr).ToNot(HaveOccurred())
  1214  						Expect(warnings).To(ConsistOf("private-domain-warnings", "shared-domain-warnings"))
  1215  						Expect(defaultRoute).To(Equal(v2action.Route{
  1216  							Domain:    domain,
  1217  							SpaceGUID: spaceGUID,
  1218  						}))
  1219  					})
  1220  				})
  1221  
  1222  				When("the domain is an HTTP Domain", func() {
  1223  					BeforeEach(func() {
  1224  						domain.Type = constant.SharedDomain
  1225  						fakeV2Actor.GetOrganizationDomainsReturns([]v2action.Domain{domain}, v2action.Warnings{"private-domain-warnings", "shared-domain-warnings"}, nil)
  1226  					})
  1227  
  1228  					It("returns an error and warnings", func() {
  1229  						Expect(executeErr).To(MatchError(actionerror.NoHostnameAndSharedDomainError{}))
  1230  						Expect(warnings).To(ConsistOf("private-domain-warnings", "shared-domain-warnings"))
  1231  					})
  1232  				})
  1233  			})
  1234  		})
  1235  
  1236  		Context("the route path is provided", func() {
  1237  			BeforeEach(func() {
  1238  				providedManifest.RoutePath = "/some-route-path"
  1239  			})
  1240  
  1241  			When("the domain is an HTTP domain", func() {
  1242  				BeforeEach(func() {
  1243  					domain.Type = constant.SharedDomain
  1244  					fakeV2Actor.GetOrganizationDomainsReturns(
  1245  						[]v2action.Domain{domain},
  1246  						v2action.Warnings{"some-organization-domain-warning"},
  1247  						nil,
  1248  					)
  1249  
  1250  					// Assumes new route
  1251  					fakeV2Actor.FindRouteBoundToSpaceWithSettingsReturns(v2action.Route{}, v2action.Warnings{"get-route-warnings"}, actionerror.RouteNotFoundError{})
  1252  				})
  1253  
  1254  				It("it uses the provided route-path for the route", func() {
  1255  					Expect(executeErr).ToNot(HaveOccurred())
  1256  					Expect(warnings).To(ConsistOf("some-organization-domain-warning", "get-route-warnings"))
  1257  					Expect(defaultRoute).To(Equal(v2action.Route{
  1258  						Domain:    domain,
  1259  						Host:      "some-app",
  1260  						SpaceGUID: spaceGUID,
  1261  						Path:      "/some-route-path",
  1262  					}))
  1263  
  1264  					Expect(fakeV2Actor.FindRouteBoundToSpaceWithSettingsCallCount()).To(Equal(1))
  1265  					Expect(fakeV2Actor.FindRouteBoundToSpaceWithSettingsArgsForCall(0)).To(Equal(v2action.Route{
  1266  						Domain:    domain,
  1267  						Host:      "some-app",
  1268  						SpaceGUID: spaceGUID,
  1269  						Path:      "/some-route-path",
  1270  					}))
  1271  				})
  1272  			})
  1273  
  1274  			When("the provided domain is a TCP domain", func() {
  1275  				BeforeEach(func() {
  1276  					domain.RouterGroupType = constant.TCPRouterGroup
  1277  					fakeV2Actor.GetOrganizationDomainsReturns(
  1278  						[]v2action.Domain{domain},
  1279  						v2action.Warnings{"some-organization-domain-warning"},
  1280  						nil,
  1281  					)
  1282  				})
  1283  
  1284  				It("returns an error", func() {
  1285  					Expect(executeErr).To(MatchError(actionerror.RoutePathWithTCPDomainError{}))
  1286  					Expect(warnings).To(ConsistOf("some-organization-domain-warning"))
  1287  				})
  1288  
  1289  			})
  1290  		})
  1291  
  1292  		When("no route settings are provided (default route)", func() {
  1293  			When("retrieving the domains is successful", func() {
  1294  				BeforeEach(func() {
  1295  					fakeV2Actor.GetOrganizationDomainsReturns(
  1296  						[]v2action.Domain{domain},
  1297  						v2action.Warnings{"private-domain-warnings", "shared-domain-warnings"},
  1298  						nil,
  1299  					)
  1300  				})
  1301  
  1302  				When("the app name is simple", func() {
  1303  					When("the route exists", func() {
  1304  						BeforeEach(func() {
  1305  							fakeV2Actor.FindRouteBoundToSpaceWithSettingsReturns(v2action.Route{
  1306  								Domain:    domain,
  1307  								GUID:      "some-route-guid",
  1308  								Host:      "some-app",
  1309  								SpaceGUID: spaceGUID,
  1310  							}, v2action.Warnings{"get-route-warnings"}, nil)
  1311  						})
  1312  
  1313  						It("returns the route and warnings", func() {
  1314  							Expect(executeErr).ToNot(HaveOccurred())
  1315  							Expect(warnings).To(ConsistOf("private-domain-warnings", "shared-domain-warnings", "get-route-warnings"))
  1316  
  1317  							Expect(defaultRoute).To(Equal(v2action.Route{
  1318  								Domain:    domain,
  1319  								GUID:      "some-route-guid",
  1320  								Host:      "some-app",
  1321  								SpaceGUID: spaceGUID,
  1322  							}))
  1323  
  1324  							Expect(fakeV2Actor.GetOrganizationDomainsCallCount()).To(Equal(1))
  1325  							Expect(fakeV2Actor.GetOrganizationDomainsArgsForCall(0)).To(Equal(orgGUID))
  1326  
  1327  							Expect(fakeV2Actor.FindRouteBoundToSpaceWithSettingsCallCount()).To(Equal(1))
  1328  							Expect(fakeV2Actor.FindRouteBoundToSpaceWithSettingsArgsForCall(0)).To(Equal(v2action.Route{
  1329  								Domain:    domain,
  1330  								Host:      strings.ToLower(providedManifest.Name),
  1331  								SpaceGUID: spaceGUID,
  1332  							}))
  1333  						})
  1334  
  1335  						When("the route is in known routes", func() {
  1336  							BeforeEach(func() {
  1337  								knownRoutes = []v2action.Route{{
  1338  									Domain:    domain,
  1339  									GUID:      "some-route-guid",
  1340  									Host:      strings.ToLower(providedManifest.Name),
  1341  									SpaceGUID: spaceGUID,
  1342  								}}
  1343  							})
  1344  
  1345  							It("should return the known route and warnings", func() {
  1346  								Expect(executeErr).ToNot(HaveOccurred())
  1347  								Expect(warnings).To(ConsistOf("private-domain-warnings", "shared-domain-warnings"))
  1348  
  1349  								Expect(defaultRoute).To(Equal(v2action.Route{
  1350  									Domain:    domain,
  1351  									GUID:      "some-route-guid",
  1352  									Host:      strings.ToLower(providedManifest.Name),
  1353  									SpaceGUID: spaceGUID,
  1354  								}))
  1355  
  1356  								Expect(fakeV2Actor.FindRouteBoundToSpaceWithSettingsCallCount()).To(Equal(0))
  1357  							})
  1358  						})
  1359  
  1360  						When("the route does not exist", func() {
  1361  							BeforeEach(func() {
  1362  								fakeV2Actor.FindRouteBoundToSpaceWithSettingsReturns(v2action.Route{}, v2action.Warnings{"get-route-warnings"}, actionerror.RouteNotFoundError{})
  1363  							})
  1364  
  1365  							It("returns a partial route", func() {
  1366  								Expect(executeErr).ToNot(HaveOccurred())
  1367  								Expect(warnings).To(ConsistOf("private-domain-warnings", "shared-domain-warnings", "get-route-warnings"))
  1368  
  1369  								Expect(defaultRoute).To(Equal(v2action.Route{Domain: domain, Host: strings.ToLower(providedManifest.Name), SpaceGUID: spaceGUID}))
  1370  							})
  1371  						})
  1372  
  1373  						When("retrieving the routes errors", func() {
  1374  							var expectedErr error
  1375  
  1376  							BeforeEach(func() {
  1377  								expectedErr = errors.New("whoops")
  1378  								fakeV2Actor.FindRouteBoundToSpaceWithSettingsReturns(v2action.Route{}, v2action.Warnings{"get-route-warnings"}, expectedErr)
  1379  							})
  1380  
  1381  							It("returns errors and warnings", func() {
  1382  								Expect(executeErr).To(MatchError(expectedErr))
  1383  								Expect(warnings).To(ConsistOf("private-domain-warnings", "shared-domain-warnings", "get-route-warnings"))
  1384  							})
  1385  						})
  1386  					})
  1387  				})
  1388  
  1389  				When("the app name is complex", func() {
  1390  					BeforeEach(func() {
  1391  						providedManifest.Name = "$Some App 1234567890"
  1392  					})
  1393  
  1394  					It("provides the sanitized application name to FindRouteBoundToSpaceWithSettings", func() {
  1395  						Expect(fakeV2Actor.FindRouteBoundToSpaceWithSettingsCallCount()).To(Equal(1))
  1396  						Expect(fakeV2Actor.FindRouteBoundToSpaceWithSettingsArgsForCall(0)).To(Equal(v2action.Route{
  1397  							Domain:    domain,
  1398  							Host:      "some-app-1234567890",
  1399  							SpaceGUID: spaceGUID,
  1400  						}))
  1401  					})
  1402  				})
  1403  
  1404  				When("the app name is not a usable hostname", func() {
  1405  					BeforeEach(func() {
  1406  						providedManifest.Name = " %^ @# **(& "
  1407  					})
  1408  
  1409  					It("provides the sanitized application name to FindRouteBoundToSpaceWithSettings", func() {
  1410  						Expect(fakeV2Actor.FindRouteBoundToSpaceWithSettingsCallCount()).To(Equal(1))
  1411  						Expect(fakeV2Actor.FindRouteBoundToSpaceWithSettingsArgsForCall(0)).To(Equal(v2action.Route{
  1412  							Domain:    domain,
  1413  							SpaceGUID: spaceGUID,
  1414  						}))
  1415  					})
  1416  				})
  1417  			})
  1418  
  1419  			When("retrieving the domains errors", func() {
  1420  				var expectedErr error
  1421  
  1422  				BeforeEach(func() {
  1423  					expectedErr = errors.New("whoops")
  1424  					fakeV2Actor.GetOrganizationDomainsReturns([]v2action.Domain{}, v2action.Warnings{"private-domain-warnings", "shared-domain-warnings"}, expectedErr)
  1425  				})
  1426  
  1427  				It("returns errors and warnings", func() {
  1428  					Expect(executeErr).To(MatchError(expectedErr))
  1429  					Expect(warnings).To(ConsistOf("private-domain-warnings", "shared-domain-warnings"))
  1430  				})
  1431  			})
  1432  		})
  1433  	})
  1434  })