github.com/Thanhphan1147/cloudfoundry-cli@v7.1.0+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 the application routes errors", func() {
   503  			BeforeEach(func() {
   504  				fakeV2Actor.GetApplicationRoutesReturns(
   505  					[]v2action.Route{},
   506  					v2action.Warnings{"route-warning"},
   507  					errors.New("some-error"),
   508  				)
   509  			})
   510  
   511  			It("returns the error", func() {
   512  				Expect(executeErr).To(MatchError("some-error"))
   513  				Expect(warnings).To(ConsistOf("route-warning"))
   514  			})
   515  		})
   516  
   517  		When("getting the application routes succeeds", func() {
   518  			// TODO: do we need this context
   519  			When("A non default route is already bound to the app", func() {
   520  				BeforeEach(func() {
   521  					fakeV2Actor.GetApplicationRoutesReturns(
   522  						[]v2action.Route{
   523  							{
   524  								Host: "some-app-sepcial",
   525  								Domain: v2action.Domain{
   526  									GUID: "some-domain-guid",
   527  									Name: "some-domain",
   528  								},
   529  								GUID:      "some-route-guid",
   530  								SpaceGUID: "some-space-guid",
   531  							},
   532  						},
   533  						v2action.Warnings{"route-warning"},
   534  						nil,
   535  					)
   536  				})
   537  
   538  				It("returns any warnings", func() {
   539  					Expect(executeErr).ToNot(HaveOccurred())
   540  					Expect(warnings).To(ConsistOf("route-warning"))
   541  
   542  					Expect(fakeV2Actor.GetApplicationRoutesCallCount()).To(Equal(1), "Expected GetApplicationRoutes to be called once, but it was not")
   543  					appGUID := fakeV2Actor.GetApplicationRoutesArgsForCall(0)
   544  					Expect(appGUID).To(Equal("some-app-guid"))
   545  
   546  					Expect(fakeV2Actor.GetOrganizationDomainsCallCount()).To(Equal(0), "Expected GetOrganizationDomains to be called once, but it was not")
   547  					Expect(fakeV2Actor.CreateRouteCallCount()).To(Equal(0), "Expected CreateRoute to not be called but it was")
   548  					Expect(fakeV2Actor.MapRouteToApplicationCallCount()).To(Equal(0), "Expected MapRouteToApplication to not be called but it was")
   549  				})
   550  			})
   551  
   552  			When("The default route is already bound to the app", func() {
   553  				BeforeEach(func() {
   554  					fakeV2Actor.GetApplicationRoutesReturns(
   555  						[]v2action.Route{
   556  							{
   557  								Host: "some-app",
   558  								Domain: v2action.Domain{
   559  									GUID: "some-domain-guid",
   560  									Name: "some-domain",
   561  								},
   562  								GUID:      "some-route-guid",
   563  								SpaceGUID: "some-space-guid",
   564  							},
   565  						},
   566  						v2action.Warnings{"route-warning"},
   567  						nil,
   568  					)
   569  				})
   570  
   571  				It("returns any warnings", func() {
   572  					Expect(executeErr).ToNot(HaveOccurred())
   573  					Expect(warnings).To(ConsistOf("route-warning"))
   574  
   575  					Expect(fakeV2Actor.GetApplicationRoutesCallCount()).To(Equal(1), "Expected GetApplicationRoutes to be called once, but it was not")
   576  					appGUID := fakeV2Actor.GetApplicationRoutesArgsForCall(0)
   577  					Expect(appGUID).To(Equal("some-app-guid"))
   578  
   579  					Expect(fakeV2Actor.CreateRouteCallCount()).To(Equal(0), "Expected CreateRoute to not be called but it was")
   580  					Expect(fakeV2Actor.MapRouteToApplicationCallCount()).To(Equal(0), "Expected MapRouteToApplication to not be called but it was")
   581  					Expect(fakeV2Actor.GetOrganizationDomainsCallCount()).To(Equal(0), "Expected GetOrganizationDomains to be called once, but it was not")
   582  				})
   583  			})
   584  
   585  			When("A route isn't bound to the app", func() {
   586  				When("getting organization domains errors", func() {
   587  					BeforeEach(func() {
   588  						fakeV2Actor.GetOrganizationDomainsReturns(
   589  							[]v2action.Domain{},
   590  							v2action.Warnings{"domain-warning"},
   591  							errors.New("some-error"))
   592  					})
   593  
   594  					It("returns the error", func() {
   595  						Expect(executeErr).To(MatchError("some-error"))
   596  						Expect(warnings).To(ConsistOf("domain-warning"))
   597  					})
   598  				})
   599  
   600  				When("getting organization domains succeeds", func() {
   601  					BeforeEach(func() {
   602  						fakeV2Actor.GetOrganizationDomainsReturns(
   603  							[]v2action.Domain{
   604  								{
   605  									GUID: "some-domain-guid",
   606  									Name: "some-domain",
   607  								},
   608  							},
   609  							v2action.Warnings{"domain-warning"},
   610  							nil,
   611  						)
   612  					})
   613  
   614  					When("finding route in space errors", func() {
   615  						BeforeEach(func() {
   616  							fakeV2Actor.FindRouteBoundToSpaceWithSettingsReturns(
   617  								v2action.Route{},
   618  								v2action.Warnings{"route-warning"},
   619  								errors.New("some-error"),
   620  							)
   621  						})
   622  
   623  						It("returns the error", func() {
   624  							Expect(executeErr).To(MatchError("some-error"))
   625  							Expect(warnings).To(ConsistOf("domain-warning", "route-warning"))
   626  						})
   627  					})
   628  
   629  					When("the route exists", func() {
   630  						BeforeEach(func() {
   631  							fakeV2Actor.FindRouteBoundToSpaceWithSettingsReturns(
   632  								v2action.Route{
   633  									GUID: "some-route-guid",
   634  									Host: "some-app",
   635  									Domain: v2action.Domain{
   636  										Name: "some-domain",
   637  										GUID: "some-domain-guid",
   638  									},
   639  									SpaceGUID: "some-space-guid",
   640  								},
   641  								v2action.Warnings{"route-warning"},
   642  								nil,
   643  							)
   644  						})
   645  
   646  						When("the map command returns an error", func() {
   647  							BeforeEach(func() {
   648  								fakeV2Actor.MapRouteToApplicationReturns(
   649  									v2action.Warnings{"map-warning"},
   650  									errors.New("some-error"),
   651  								)
   652  							})
   653  
   654  							It("returns the error", func() {
   655  								Expect(executeErr).To(MatchError("some-error"))
   656  								Expect(warnings).To(ConsistOf("domain-warning", "route-warning", "map-warning"))
   657  							})
   658  						})
   659  
   660  						When("the map command succeeds", func() {
   661  							BeforeEach(func() {
   662  								fakeV2Actor.MapRouteToApplicationReturns(
   663  									v2action.Warnings{"map-warning"},
   664  									nil,
   665  								)
   666  							})
   667  
   668  							It("maps the route to the app and returns any warnings", func() {
   669  								Expect(executeErr).ToNot(HaveOccurred())
   670  								Expect(warnings).To(ConsistOf("domain-warning", "route-warning", "map-warning"))
   671  
   672  								Expect(fakeV2Actor.FindRouteBoundToSpaceWithSettingsCallCount()).To(Equal(1), "Expected FindRouteBoundToSpaceWithSettings to be called once, but it was not")
   673  								spaceRoute := fakeV2Actor.FindRouteBoundToSpaceWithSettingsArgsForCall(0)
   674  								Expect(spaceRoute).To(Equal(v2action.Route{
   675  									Host: "some-app",
   676  									Domain: v2action.Domain{
   677  										Name: "some-domain",
   678  										GUID: "some-domain-guid",
   679  									},
   680  									SpaceGUID: "some-space-guid",
   681  								}))
   682  
   683  								Expect(fakeV2Actor.MapRouteToApplicationCallCount()).To(Equal(1), "Expected MapRouteToApplication to be called once, but it was not")
   684  								routeGUID, appGUID := fakeV2Actor.MapRouteToApplicationArgsForCall(0)
   685  								Expect(routeGUID).To(Equal("some-route-guid"))
   686  								Expect(appGUID).To(Equal("some-app-guid"))
   687  							})
   688  						})
   689  					})
   690  
   691  					When("the route does not exist", func() {
   692  						BeforeEach(func() {
   693  							fakeV2Actor.FindRouteBoundToSpaceWithSettingsReturns(
   694  								v2action.Route{},
   695  								v2action.Warnings{"route-warning"},
   696  								actionerror.RouteNotFoundError{},
   697  							)
   698  						})
   699  
   700  						When("the create route command errors", func() {
   701  							BeforeEach(func() {
   702  								fakeV2Actor.CreateRouteReturns(
   703  									v2action.Route{},
   704  									v2action.Warnings{"route-create-warning"},
   705  									errors.New("some-error"),
   706  								)
   707  							})
   708  
   709  							It("returns the error", func() {
   710  								Expect(executeErr).To(MatchError("some-error"))
   711  								Expect(warnings).To(ConsistOf("domain-warning", "route-warning", "route-create-warning"))
   712  							})
   713  						})
   714  
   715  						When("the create route command succeeds", func() {
   716  							BeforeEach(func() {
   717  								fakeV2Actor.CreateRouteReturns(
   718  									v2action.Route{
   719  										GUID: "some-route-guid",
   720  										Host: "some-app",
   721  										Domain: v2action.Domain{
   722  											Name: "some-domain",
   723  											GUID: "some-domain-guid",
   724  										},
   725  										SpaceGUID: "some-space-guid",
   726  									},
   727  									v2action.Warnings{"route-create-warning"},
   728  									nil,
   729  								)
   730  							})
   731  
   732  							When("the map command errors", func() {
   733  								BeforeEach(func() {
   734  									fakeV2Actor.MapRouteToApplicationReturns(
   735  										v2action.Warnings{"map-warning"},
   736  										errors.New("some-error"),
   737  									)
   738  								})
   739  
   740  								It("returns the error", func() {
   741  									Expect(executeErr).To(MatchError("some-error"))
   742  									Expect(warnings).To(ConsistOf("domain-warning", "route-warning", "route-create-warning", "map-warning"))
   743  								})
   744  							})
   745  							When("the map command succeeds", func() {
   746  
   747  								BeforeEach(func() {
   748  									fakeV2Actor.MapRouteToApplicationReturns(
   749  										v2action.Warnings{"map-warning"},
   750  										nil,
   751  									)
   752  								})
   753  
   754  								It("creates the route, maps it to the app, and returns any warnings", func() {
   755  									Expect(executeErr).ToNot(HaveOccurred())
   756  									Expect(warnings).To(ConsistOf("domain-warning", "route-warning", "route-create-warning", "map-warning"))
   757  
   758  									Expect(fakeV2Actor.CreateRouteCallCount()).To(Equal(1), "Expected CreateRoute to be called once, but it was not")
   759  									defaultRoute, shouldGeneratePort := fakeV2Actor.CreateRouteArgsForCall(0)
   760  									Expect(defaultRoute).To(Equal(v2action.Route{
   761  										Host: "some-app",
   762  										Domain: v2action.Domain{
   763  											Name: "some-domain",
   764  											GUID: "some-domain-guid",
   765  										},
   766  										SpaceGUID: "some-space-guid",
   767  									}))
   768  									Expect(shouldGeneratePort).To(BeFalse())
   769  
   770  									Expect(fakeV2Actor.FindRouteBoundToSpaceWithSettingsCallCount()).To(Equal(1), "Expected FindRouteBoundToSpaceWithSettings to be called once, but it was not")
   771  									spaceRoute := fakeV2Actor.FindRouteBoundToSpaceWithSettingsArgsForCall(0)
   772  									Expect(spaceRoute).To(Equal(v2action.Route{
   773  										Host: "some-app",
   774  										Domain: v2action.Domain{
   775  											Name: "some-domain",
   776  											GUID: "some-domain-guid",
   777  										},
   778  										SpaceGUID: "some-space-guid",
   779  									}))
   780  
   781  									Expect(fakeV2Actor.MapRouteToApplicationCallCount()).To(Equal(1), "Expected MapRouteToApplication to be called once, but it was not")
   782  									routeGUID, appGUID := fakeV2Actor.MapRouteToApplicationArgsForCall(0)
   783  									Expect(routeGUID).To(Equal("some-route-guid"))
   784  									Expect(appGUID).To(Equal("some-app-guid"))
   785  								})
   786  							})
   787  						})
   788  					})
   789  				})
   790  			})
   791  		})
   792  	})
   793  
   794  	Describe("CreateRoutes", func() {
   795  		var (
   796  			config ApplicationConfig
   797  
   798  			returnedConfig ApplicationConfig
   799  			createdRoutes  bool
   800  			warnings       Warnings
   801  			executeErr     error
   802  		)
   803  
   804  		BeforeEach(func() {
   805  			config = ApplicationConfig{}
   806  		})
   807  
   808  		JustBeforeEach(func() {
   809  			returnedConfig, createdRoutes, warnings, executeErr = actor.CreateRoutes(config)
   810  		})
   811  
   812  		Describe("when routes need to be created", func() {
   813  			BeforeEach(func() {
   814  				config.DesiredRoutes = []v2action.Route{
   815  					{GUID: "", Host: "some-route-1"},
   816  					{GUID: "some-route-guid-2", Host: "some-route-2"},
   817  					{GUID: "", Host: "some-route-3"},
   818  					{GUID: "", Host: "", Domain: v2action.Domain{RouterGroupType: constant.TCPRouterGroup}},
   819  				}
   820  			})
   821  
   822  			When("the creation is successful", func() {
   823  				BeforeEach(func() {
   824  					fakeV2Actor.CreateRouteReturnsOnCall(0, v2action.Route{GUID: "some-route-guid-1", Host: "some-route-1"}, v2action.Warnings{"create-route-warning"}, nil)
   825  					fakeV2Actor.CreateRouteReturnsOnCall(1, v2action.Route{GUID: "some-route-guid-3", Host: "some-route-3"}, v2action.Warnings{"create-route-warning"}, nil)
   826  					fakeV2Actor.CreateRouteReturnsOnCall(2, v2action.Route{GUID: "some-route-guid-4", Domain: v2action.Domain{RouterGroupType: constant.TCPRouterGroup}}, v2action.Warnings{"create-route-warning"}, nil)
   827  				})
   828  
   829  				It("only creates the routes that do not exist", func() {
   830  					Expect(executeErr).ToNot(HaveOccurred())
   831  					Expect(warnings).To(ConsistOf("create-route-warning", "create-route-warning", "create-route-warning"))
   832  					Expect(createdRoutes).To(BeTrue())
   833  					Expect(returnedConfig.DesiredRoutes).To(Equal([]v2action.Route{
   834  						{GUID: "some-route-guid-1", Host: "some-route-1"},
   835  						{GUID: "some-route-guid-2", Host: "some-route-2"},
   836  						{GUID: "some-route-guid-3", Host: "some-route-3"},
   837  						{GUID: "some-route-guid-4", Domain: v2action.Domain{RouterGroupType: constant.TCPRouterGroup}},
   838  					}))
   839  
   840  					Expect(fakeV2Actor.CreateRouteCallCount()).To(Equal(3))
   841  
   842  					passedRoute, randomRoute := fakeV2Actor.CreateRouteArgsForCall(0)
   843  					Expect(passedRoute).To(Equal(v2action.Route{Host: "some-route-1"}))
   844  					Expect(randomRoute).To(BeFalse())
   845  
   846  					passedRoute, randomRoute = fakeV2Actor.CreateRouteArgsForCall(1)
   847  					Expect(passedRoute).To(Equal(v2action.Route{Host: "some-route-3"}))
   848  					Expect(randomRoute).To(BeFalse())
   849  
   850  					passedRoute, randomRoute = fakeV2Actor.CreateRouteArgsForCall(2)
   851  					Expect(passedRoute).To(Equal(v2action.Route{GUID: "", Host: "", Domain: v2action.Domain{RouterGroupType: constant.TCPRouterGroup}}))
   852  					Expect(randomRoute).To(BeTrue())
   853  				})
   854  			})
   855  
   856  			When("the creation errors", func() {
   857  				var expectedErr error
   858  
   859  				BeforeEach(func() {
   860  					expectedErr = errors.New("oh my")
   861  					fakeV2Actor.CreateRouteReturns(
   862  						v2action.Route{},
   863  						v2action.Warnings{"create-route-warning"},
   864  						expectedErr)
   865  				})
   866  
   867  				It("sends the warnings and errors and returns true", func() {
   868  					Expect(executeErr).To(MatchError(expectedErr))
   869  					Expect(warnings).To(ConsistOf("create-route-warning"))
   870  				})
   871  			})
   872  		})
   873  
   874  		When("no routes are created", func() {
   875  			BeforeEach(func() {
   876  				config.DesiredRoutes = []v2action.Route{
   877  					{GUID: "some-route-guid-1", Host: "some-route-1"},
   878  					{GUID: "some-route-guid-2", Host: "some-route-2"},
   879  					{GUID: "some-route-guid-3", Host: "some-route-3"},
   880  				}
   881  			})
   882  
   883  			It("returns false", func() {
   884  				Expect(createdRoutes).To(BeFalse())
   885  			})
   886  		})
   887  	})
   888  
   889  	Describe("GenerateRandomRoute", func() {
   890  		var (
   891  			spaceGUID string
   892  			orgGUID   string
   893  
   894  			randomRoute v2action.Route
   895  			warnings    Warnings
   896  			executeErr  error
   897  
   898  			domain      v2action.Domain
   899  			manifestApp manifest.Application
   900  		)
   901  
   902  		BeforeEach(func() {
   903  			manifestApp = manifest.Application{
   904  				Name: "some a$pp nAme",
   905  			}
   906  			spaceGUID = "some-space-guid"
   907  			orgGUID = "some-org-guid"
   908  			domain = v2action.Domain{}
   909  		})
   910  
   911  		JustBeforeEach(func() {
   912  			randomRoute, warnings, executeErr = actor.GenerateRandomRoute(manifestApp, spaceGUID, orgGUID)
   913  		})
   914  
   915  		When("a domain is specified", func() {
   916  			BeforeEach(func() {
   917  				manifestApp.Domain = "some-domain"
   918  				domain.Name = "some-domain"
   919  				fakeRandomWordGenerator.RandomAdjectiveReturns("striped")
   920  				fakeRandomWordGenerator.RandomNounReturns("apple")
   921  				fakeRandomWordGenerator.RandomTwoLettersReturns("ab")
   922  
   923  				fakeV2Actor.GetDomainsByNameAndOrganizationReturns(
   924  					[]v2action.Domain{domain},
   925  					v2action.Warnings{"some-organization-domain-warning"},
   926  					nil,
   927  				)
   928  			})
   929  
   930  			It("uses the specified domain to generate a route", func() {
   931  				Expect(executeErr).ToNot(HaveOccurred())
   932  				Expect(randomRoute).To(Equal(v2action.Route{
   933  					Domain:    domain,
   934  					Host:      "some-app-name-striped-apple-ab",
   935  					SpaceGUID: spaceGUID,
   936  				}))
   937  				Expect(warnings).To(ConsistOf("some-organization-domain-warning"))
   938  
   939  				Expect(fakeV2Actor.GetDomainsByNameAndOrganizationCallCount()).To(Equal(1))
   940  				domainsArg, orgGUIDArg := fakeV2Actor.GetDomainsByNameAndOrganizationArgsForCall(0)
   941  				Expect(domainsArg).To(ConsistOf("some-domain"))
   942  				Expect(orgGUIDArg).To(Equal("some-org-guid"))
   943  			})
   944  		})
   945  
   946  		When("no domain is specified", func() {
   947  			When("the default domain is a tcp domain", func() {
   948  				BeforeEach(func() {
   949  					domain.RouterGroupType = constant.TCPRouterGroup
   950  					fakeV2Actor.GetOrganizationDomainsReturns(
   951  						[]v2action.Domain{domain},
   952  						v2action.Warnings{"some-organization-domain-warning"},
   953  						nil,
   954  					)
   955  				})
   956  
   957  				It("generates a route with a randomly generated server side port number", func() {
   958  					Expect(executeErr).ToNot(HaveOccurred())
   959  					Expect(randomRoute).To(Equal(v2action.Route{
   960  						Domain:    domain,
   961  						SpaceGUID: spaceGUID,
   962  					}))
   963  					Expect(warnings).To(ConsistOf("some-organization-domain-warning"))
   964  
   965  					Expect(fakeV2Actor.GetOrganizationDomainsCallCount()).To(Equal(1))
   966  					Expect(fakeV2Actor.GetOrganizationDomainsArgsForCall(0)).To(Equal(orgGUID))
   967  				})
   968  			})
   969  
   970  			When("the default domain is an http domain", func() {
   971  				BeforeEach(func() {
   972  					domain.RouterGroupType = constant.HTTPRouterGroup
   973  					fakeV2Actor.GetOrganizationDomainsReturns(
   974  						[]v2action.Domain{domain},
   975  						v2action.Warnings{"some-organization-domain-warning"},
   976  						nil,
   977  					)
   978  					fakeRandomWordGenerator.RandomAdjectiveReturns("striped")
   979  					fakeRandomWordGenerator.RandomNounReturns("apple")
   980  					fakeRandomWordGenerator.RandomTwoLettersReturns("ab")
   981  				})
   982  
   983  				When("the app name is partially sanitized", func() {
   984  					BeforeEach(func() {
   985  						manifestApp.Name = "a--b"
   986  					})
   987  
   988  					It("generates a route whose hostname is a sanitized app name and two randomly generated words", func() {
   989  						Expect(executeErr).ToNot(HaveOccurred())
   990  						Expect(randomRoute).To(Equal(v2action.Route{
   991  							Domain:    domain,
   992  							SpaceGUID: spaceGUID,
   993  							Host:      "a--b-striped-apple-ab",
   994  						}))
   995  						Expect(warnings).To(ConsistOf("some-organization-domain-warning"))
   996  					})
   997  				})
   998  
   999  				When("the app name is fully sanitized", func() {
  1000  					BeforeEach(func() {
  1001  						manifestApp.Name = "@@@"
  1002  					})
  1003  
  1004  					It("generates a route whose hostname is a sanitized app name and two randomly generated words", func() {
  1005  						Expect(executeErr).ToNot(HaveOccurred())
  1006  						Expect(randomRoute).To(Equal(v2action.Route{
  1007  							Domain:    domain,
  1008  							SpaceGUID: spaceGUID,
  1009  							Host:      "striped-apple-ab",
  1010  						}))
  1011  						Expect(warnings).To(ConsistOf("some-organization-domain-warning"))
  1012  					})
  1013  				})
  1014  			})
  1015  
  1016  			When("the default domain lookup fails", func() {
  1017  				BeforeEach(func() {
  1018  					fakeV2Actor.GetOrganizationDomainsReturns(
  1019  						[]v2action.Domain{domain},
  1020  						v2action.Warnings{"some-organization-domain-warning"},
  1021  						errors.New("some-error"),
  1022  					)
  1023  				})
  1024  				It("returns an error and a warning", func() {
  1025  					Expect(executeErr).To(MatchError("some-error"))
  1026  					Expect(warnings).To(ConsistOf("some-organization-domain-warning"))
  1027  				})
  1028  			})
  1029  		})
  1030  	})
  1031  
  1032  	Describe("GetGeneratedRoute", func() {
  1033  		var (
  1034  			providedManifest manifest.Application
  1035  			orgGUID          string
  1036  			spaceGUID        string
  1037  			knownRoutes      []v2action.Route
  1038  
  1039  			defaultRoute v2action.Route
  1040  			warnings     Warnings
  1041  			executeErr   error
  1042  
  1043  			domain v2action.Domain
  1044  		)
  1045  
  1046  		BeforeEach(func() {
  1047  			providedManifest = manifest.Application{
  1048  				Name: "Some-App",
  1049  			}
  1050  			orgGUID = "some-org-guid"
  1051  			spaceGUID = "some-space-guid"
  1052  			knownRoutes = nil
  1053  
  1054  			domain = v2action.Domain{
  1055  				Name: "shared-domain.com",
  1056  				GUID: "some-shared-domain-guid",
  1057  			}
  1058  		})
  1059  
  1060  		JustBeforeEach(func() {
  1061  			defaultRoute, warnings, executeErr = actor.GetGeneratedRoute(providedManifest, orgGUID, spaceGUID, knownRoutes)
  1062  		})
  1063  
  1064  		Context("the domain is provided", func() {
  1065  			BeforeEach(func() {
  1066  				providedManifest.Domain = "shared-domain.com"
  1067  			})
  1068  
  1069  			When("the provided domain exists", func() {
  1070  				BeforeEach(func() {
  1071  					domain.Type = constant.SharedDomain
  1072  
  1073  					// Assumes new route
  1074  					fakeV2Actor.FindRouteBoundToSpaceWithSettingsReturns(v2action.Route{}, v2action.Warnings{"get-route-warnings"}, actionerror.RouteNotFoundError{})
  1075  				})
  1076  
  1077  				When("the provided domain is an HTTP domain", func() {
  1078  					BeforeEach(func() {
  1079  						fakeV2Actor.GetDomainsByNameAndOrganizationReturns(
  1080  							[]v2action.Domain{domain},
  1081  							v2action.Warnings{"some-organization-domain-warning"},
  1082  							nil,
  1083  						)
  1084  					})
  1085  
  1086  					It("it uses the provided domain instead of the first shared domain", func() {
  1087  						Expect(executeErr).ToNot(HaveOccurred())
  1088  						Expect(warnings).To(ConsistOf("some-organization-domain-warning", "get-route-warnings"))
  1089  						Expect(defaultRoute).To(Equal(v2action.Route{
  1090  							Domain:    domain,
  1091  							Host:      strings.ToLower(providedManifest.Name),
  1092  							SpaceGUID: spaceGUID,
  1093  						}))
  1094  
  1095  						Expect(fakeV2Actor.GetDomainsByNameAndOrganizationCallCount()).To(Equal(1))
  1096  						domainNamesArg, orgGUIDArg := fakeV2Actor.GetDomainsByNameAndOrganizationArgsForCall(0)
  1097  						Expect(domainNamesArg).To(Equal([]string{"shared-domain.com"}))
  1098  						Expect(orgGUIDArg).To(Equal(orgGUID))
  1099  
  1100  						Expect(fakeV2Actor.FindRouteBoundToSpaceWithSettingsCallCount()).To(Equal(1))
  1101  						Expect(fakeV2Actor.FindRouteBoundToSpaceWithSettingsArgsForCall(0)).To(Equal(v2action.Route{
  1102  							Domain:    domain,
  1103  							Host:      strings.ToLower(providedManifest.Name),
  1104  							SpaceGUID: spaceGUID,
  1105  						}))
  1106  					})
  1107  				})
  1108  
  1109  				When("the provided domain is an TCP domain", func() {
  1110  					BeforeEach(func() {
  1111  						domain.RouterGroupType = constant.TCPRouterGroup
  1112  
  1113  						fakeV2Actor.GetDomainsByNameAndOrganizationReturns(
  1114  							[]v2action.Domain{domain},
  1115  							v2action.Warnings{"some-organization-domain-warning"},
  1116  							nil,
  1117  						)
  1118  					})
  1119  
  1120  					It("it uses the provided domain instead of the first shared domain and has no host", func() {
  1121  						Expect(executeErr).ToNot(HaveOccurred())
  1122  						Expect(warnings).To(ConsistOf("some-organization-domain-warning"))
  1123  						Expect(defaultRoute).To(Equal(v2action.Route{
  1124  							Domain:    domain,
  1125  							SpaceGUID: spaceGUID,
  1126  						}))
  1127  
  1128  						Expect(fakeV2Actor.GetDomainsByNameAndOrganizationCallCount()).To(Equal(1))
  1129  						domainNamesArg, orgGUIDArg := fakeV2Actor.GetDomainsByNameAndOrganizationArgsForCall(0)
  1130  						Expect(domainNamesArg).To(Equal([]string{"shared-domain.com"}))
  1131  						Expect(orgGUIDArg).To(Equal(orgGUID))
  1132  
  1133  						Expect(fakeV2Actor.FindRouteBoundToSpaceWithSettingsCallCount()).To(Equal(0))
  1134  					})
  1135  				})
  1136  			})
  1137  
  1138  			When("the provided domain does not exist", func() {
  1139  				BeforeEach(func() {
  1140  					fakeV2Actor.GetDomainsByNameAndOrganizationReturns(
  1141  						[]v2action.Domain{},
  1142  						v2action.Warnings{"some-organization-domain-warning"},
  1143  						nil,
  1144  					)
  1145  				})
  1146  
  1147  				It("returns an DomainNotFoundError", func() {
  1148  					Expect(executeErr).To(MatchError(actionerror.DomainNotFoundError{Name: "shared-domain.com"}))
  1149  					Expect(warnings).To(ConsistOf("some-organization-domain-warning"))
  1150  				})
  1151  			})
  1152  		})
  1153  
  1154  		Context("the hostname is provided", func() {
  1155  			BeforeEach(func() {
  1156  				providedManifest.Hostname = "some HO_ST"
  1157  			})
  1158  
  1159  			When("the domain is an HTTP domain", func() {
  1160  				BeforeEach(func() {
  1161  					domain.Type = constant.SharedDomain
  1162  					fakeV2Actor.GetOrganizationDomainsReturns(
  1163  						[]v2action.Domain{domain},
  1164  						v2action.Warnings{"some-organization-domain-warning"},
  1165  						nil,
  1166  					)
  1167  
  1168  					// Assumes new route
  1169  					fakeV2Actor.FindRouteBoundToSpaceWithSettingsReturns(v2action.Route{}, v2action.Warnings{"get-route-warnings"}, actionerror.RouteNotFoundError{})
  1170  				})
  1171  
  1172  				It("it uses the provided hostname instead of the app name", func() {
  1173  					Expect(executeErr).ToNot(HaveOccurred())
  1174  					Expect(warnings).To(ConsistOf("some-organization-domain-warning", "get-route-warnings"))
  1175  					Expect(defaultRoute).To(Equal(v2action.Route{
  1176  						Domain:    domain,
  1177  						Host:      "some-host",
  1178  						SpaceGUID: spaceGUID,
  1179  					}))
  1180  
  1181  					Expect(fakeV2Actor.FindRouteBoundToSpaceWithSettingsCallCount()).To(Equal(1))
  1182  					Expect(fakeV2Actor.FindRouteBoundToSpaceWithSettingsArgsForCall(0)).To(Equal(v2action.Route{
  1183  						Domain:    domain,
  1184  						Host:      "some-host",
  1185  						SpaceGUID: spaceGUID,
  1186  					}))
  1187  				})
  1188  			})
  1189  
  1190  			When("the provided domain is an TCP domain", func() {
  1191  				BeforeEach(func() {
  1192  					domain.RouterGroupType = constant.TCPRouterGroup
  1193  					fakeV2Actor.GetOrganizationDomainsReturns(
  1194  						[]v2action.Domain{domain},
  1195  						v2action.Warnings{"some-organization-domain-warning"},
  1196  						nil,
  1197  					)
  1198  				})
  1199  
  1200  				It("returns an error", func() {
  1201  					Expect(executeErr).To(MatchError(actionerror.HostnameWithTCPDomainError{}))
  1202  					Expect(warnings).To(ConsistOf("some-organization-domain-warning"))
  1203  				})
  1204  			})
  1205  		})
  1206  
  1207  		When("no hostname is requested", func() {
  1208  			BeforeEach(func() {
  1209  				providedManifest.NoHostname = true
  1210  
  1211  				// Assumes new route
  1212  				fakeV2Actor.FindRouteBoundToSpaceWithSettingsReturns(v2action.Route{}, v2action.Warnings{"get-route-warnings"}, actionerror.RouteNotFoundError{})
  1213  			})
  1214  
  1215  			Context("the domain is a private domain", func() {
  1216  				BeforeEach(func() {
  1217  					domain.Type = constant.PrivateDomain
  1218  					fakeV2Actor.GetOrganizationDomainsReturns([]v2action.Domain{domain}, nil, nil)
  1219  				})
  1220  
  1221  				It("does not set the hostname for the route", func() {
  1222  					Expect(executeErr).ToNot(HaveOccurred())
  1223  					Expect(defaultRoute).To(Equal(v2action.Route{
  1224  						Domain:    domain,
  1225  						SpaceGUID: spaceGUID,
  1226  					}))
  1227  
  1228  					Expect(fakeV2Actor.FindRouteBoundToSpaceWithSettingsCallCount()).To(Equal(1))
  1229  					Expect(fakeV2Actor.FindRouteBoundToSpaceWithSettingsArgsForCall(0)).To(Equal(v2action.Route{
  1230  						Domain:    domain,
  1231  						SpaceGUID: spaceGUID,
  1232  					}))
  1233  				})
  1234  			})
  1235  
  1236  			Context("the domain is a shared domain", func() {
  1237  				When("the domain is a TCP Domain", func() {
  1238  					BeforeEach(func() {
  1239  						domain.Type = constant.SharedDomain
  1240  						domain.RouterGroupType = constant.TCPRouterGroup
  1241  						fakeV2Actor.GetOrganizationDomainsReturns([]v2action.Domain{domain}, v2action.Warnings{"private-domain-warnings", "shared-domain-warnings"}, nil)
  1242  					})
  1243  
  1244  					It("returns a TCP route", func() {
  1245  						Expect(executeErr).ToNot(HaveOccurred())
  1246  						Expect(warnings).To(ConsistOf("private-domain-warnings", "shared-domain-warnings"))
  1247  						Expect(defaultRoute).To(Equal(v2action.Route{
  1248  							Domain:    domain,
  1249  							SpaceGUID: spaceGUID,
  1250  						}))
  1251  					})
  1252  				})
  1253  
  1254  				When("the domain is an HTTP Domain", func() {
  1255  					BeforeEach(func() {
  1256  						domain.Type = constant.SharedDomain
  1257  						fakeV2Actor.GetOrganizationDomainsReturns([]v2action.Domain{domain}, v2action.Warnings{"private-domain-warnings", "shared-domain-warnings"}, nil)
  1258  					})
  1259  
  1260  					It("returns an error and warnings", func() {
  1261  						Expect(executeErr).To(MatchError(actionerror.NoHostnameAndSharedDomainError{}))
  1262  						Expect(warnings).To(ConsistOf("private-domain-warnings", "shared-domain-warnings"))
  1263  					})
  1264  				})
  1265  			})
  1266  		})
  1267  
  1268  		Context("the route path is provided", func() {
  1269  			BeforeEach(func() {
  1270  				providedManifest.RoutePath = "/some-route-path"
  1271  			})
  1272  
  1273  			When("the domain is an HTTP domain", func() {
  1274  				BeforeEach(func() {
  1275  					domain.Type = constant.SharedDomain
  1276  					fakeV2Actor.GetOrganizationDomainsReturns(
  1277  						[]v2action.Domain{domain},
  1278  						v2action.Warnings{"some-organization-domain-warning"},
  1279  						nil,
  1280  					)
  1281  
  1282  					// Assumes new route
  1283  					fakeV2Actor.FindRouteBoundToSpaceWithSettingsReturns(v2action.Route{}, v2action.Warnings{"get-route-warnings"}, actionerror.RouteNotFoundError{})
  1284  				})
  1285  
  1286  				It("it uses the provided route-path for the route", func() {
  1287  					Expect(executeErr).ToNot(HaveOccurred())
  1288  					Expect(warnings).To(ConsistOf("some-organization-domain-warning", "get-route-warnings"))
  1289  					Expect(defaultRoute).To(Equal(v2action.Route{
  1290  						Domain:    domain,
  1291  						Host:      "some-app",
  1292  						SpaceGUID: spaceGUID,
  1293  						Path:      "/some-route-path",
  1294  					}))
  1295  
  1296  					Expect(fakeV2Actor.FindRouteBoundToSpaceWithSettingsCallCount()).To(Equal(1))
  1297  					Expect(fakeV2Actor.FindRouteBoundToSpaceWithSettingsArgsForCall(0)).To(Equal(v2action.Route{
  1298  						Domain:    domain,
  1299  						Host:      "some-app",
  1300  						SpaceGUID: spaceGUID,
  1301  						Path:      "/some-route-path",
  1302  					}))
  1303  				})
  1304  			})
  1305  
  1306  			When("the provided domain is a TCP domain", func() {
  1307  				BeforeEach(func() {
  1308  					domain.RouterGroupType = constant.TCPRouterGroup
  1309  					fakeV2Actor.GetOrganizationDomainsReturns(
  1310  						[]v2action.Domain{domain},
  1311  						v2action.Warnings{"some-organization-domain-warning"},
  1312  						nil,
  1313  					)
  1314  				})
  1315  
  1316  				It("returns an error", func() {
  1317  					Expect(executeErr).To(MatchError(actionerror.RoutePathWithTCPDomainError{}))
  1318  					Expect(warnings).To(ConsistOf("some-organization-domain-warning"))
  1319  				})
  1320  
  1321  			})
  1322  		})
  1323  
  1324  		When("no route settings are provided (default route)", func() {
  1325  			When("retrieving the domains is successful", func() {
  1326  				BeforeEach(func() {
  1327  					fakeV2Actor.GetOrganizationDomainsReturns(
  1328  						[]v2action.Domain{domain},
  1329  						v2action.Warnings{"private-domain-warnings", "shared-domain-warnings"},
  1330  						nil,
  1331  					)
  1332  				})
  1333  
  1334  				When("the app name is simple", func() {
  1335  					When("the route exists", func() {
  1336  						BeforeEach(func() {
  1337  							fakeV2Actor.FindRouteBoundToSpaceWithSettingsReturns(v2action.Route{
  1338  								Domain:    domain,
  1339  								GUID:      "some-route-guid",
  1340  								Host:      "some-app",
  1341  								SpaceGUID: spaceGUID,
  1342  							}, v2action.Warnings{"get-route-warnings"}, nil)
  1343  						})
  1344  
  1345  						It("returns the route and warnings", func() {
  1346  							Expect(executeErr).ToNot(HaveOccurred())
  1347  							Expect(warnings).To(ConsistOf("private-domain-warnings", "shared-domain-warnings", "get-route-warnings"))
  1348  
  1349  							Expect(defaultRoute).To(Equal(v2action.Route{
  1350  								Domain:    domain,
  1351  								GUID:      "some-route-guid",
  1352  								Host:      "some-app",
  1353  								SpaceGUID: spaceGUID,
  1354  							}))
  1355  
  1356  							Expect(fakeV2Actor.GetOrganizationDomainsCallCount()).To(Equal(1))
  1357  							Expect(fakeV2Actor.GetOrganizationDomainsArgsForCall(0)).To(Equal(orgGUID))
  1358  
  1359  							Expect(fakeV2Actor.FindRouteBoundToSpaceWithSettingsCallCount()).To(Equal(1))
  1360  							Expect(fakeV2Actor.FindRouteBoundToSpaceWithSettingsArgsForCall(0)).To(Equal(v2action.Route{
  1361  								Domain:    domain,
  1362  								Host:      strings.ToLower(providedManifest.Name),
  1363  								SpaceGUID: spaceGUID,
  1364  							}))
  1365  						})
  1366  
  1367  						When("the route is in known routes", func() {
  1368  							BeforeEach(func() {
  1369  								knownRoutes = []v2action.Route{{
  1370  									Domain:    domain,
  1371  									GUID:      "some-route-guid",
  1372  									Host:      strings.ToLower(providedManifest.Name),
  1373  									SpaceGUID: spaceGUID,
  1374  								}}
  1375  							})
  1376  
  1377  							It("should return the known route and warnings", func() {
  1378  								Expect(executeErr).ToNot(HaveOccurred())
  1379  								Expect(warnings).To(ConsistOf("private-domain-warnings", "shared-domain-warnings"))
  1380  
  1381  								Expect(defaultRoute).To(Equal(v2action.Route{
  1382  									Domain:    domain,
  1383  									GUID:      "some-route-guid",
  1384  									Host:      strings.ToLower(providedManifest.Name),
  1385  									SpaceGUID: spaceGUID,
  1386  								}))
  1387  
  1388  								Expect(fakeV2Actor.FindRouteBoundToSpaceWithSettingsCallCount()).To(Equal(0))
  1389  							})
  1390  						})
  1391  
  1392  						When("the route does not exist", func() {
  1393  							BeforeEach(func() {
  1394  								fakeV2Actor.FindRouteBoundToSpaceWithSettingsReturns(v2action.Route{}, v2action.Warnings{"get-route-warnings"}, actionerror.RouteNotFoundError{})
  1395  							})
  1396  
  1397  							It("returns a partial route", func() {
  1398  								Expect(executeErr).ToNot(HaveOccurred())
  1399  								Expect(warnings).To(ConsistOf("private-domain-warnings", "shared-domain-warnings", "get-route-warnings"))
  1400  
  1401  								Expect(defaultRoute).To(Equal(v2action.Route{Domain: domain, Host: strings.ToLower(providedManifest.Name), SpaceGUID: spaceGUID}))
  1402  							})
  1403  						})
  1404  
  1405  						When("retrieving the routes errors", func() {
  1406  							var expectedErr error
  1407  
  1408  							BeforeEach(func() {
  1409  								expectedErr = errors.New("whoops")
  1410  								fakeV2Actor.FindRouteBoundToSpaceWithSettingsReturns(v2action.Route{}, v2action.Warnings{"get-route-warnings"}, expectedErr)
  1411  							})
  1412  
  1413  							It("returns errors and warnings", func() {
  1414  								Expect(executeErr).To(MatchError(expectedErr))
  1415  								Expect(warnings).To(ConsistOf("private-domain-warnings", "shared-domain-warnings", "get-route-warnings"))
  1416  							})
  1417  						})
  1418  					})
  1419  				})
  1420  
  1421  				When("the app name is complex", func() {
  1422  					BeforeEach(func() {
  1423  						providedManifest.Name = "$Some App 1234567890"
  1424  					})
  1425  
  1426  					It("provides the sanitized application name to FindRouteBoundToSpaceWithSettings", func() {
  1427  						Expect(fakeV2Actor.FindRouteBoundToSpaceWithSettingsCallCount()).To(Equal(1))
  1428  						Expect(fakeV2Actor.FindRouteBoundToSpaceWithSettingsArgsForCall(0)).To(Equal(v2action.Route{
  1429  							Domain:    domain,
  1430  							Host:      "some-app-1234567890",
  1431  							SpaceGUID: spaceGUID,
  1432  						}))
  1433  					})
  1434  				})
  1435  
  1436  				When("the app name is not a usable hostname", func() {
  1437  					BeforeEach(func() {
  1438  						providedManifest.Name = " %^ @# **(& "
  1439  					})
  1440  
  1441  					It("provides the sanitized application name to FindRouteBoundToSpaceWithSettings", func() {
  1442  						Expect(fakeV2Actor.FindRouteBoundToSpaceWithSettingsCallCount()).To(Equal(1))
  1443  						Expect(fakeV2Actor.FindRouteBoundToSpaceWithSettingsArgsForCall(0)).To(Equal(v2action.Route{
  1444  							Domain:    domain,
  1445  							SpaceGUID: spaceGUID,
  1446  						}))
  1447  					})
  1448  				})
  1449  			})
  1450  
  1451  			When("retrieving the domains errors", func() {
  1452  				var expectedErr error
  1453  
  1454  				BeforeEach(func() {
  1455  					expectedErr = errors.New("whoops")
  1456  					fakeV2Actor.GetOrganizationDomainsReturns([]v2action.Domain{}, v2action.Warnings{"private-domain-warnings", "shared-domain-warnings"}, expectedErr)
  1457  				})
  1458  
  1459  				It("returns errors and warnings", func() {
  1460  					Expect(executeErr).To(MatchError(expectedErr))
  1461  					Expect(warnings).To(ConsistOf("private-domain-warnings", "shared-domain-warnings"))
  1462  				})
  1463  			})
  1464  		})
  1465  	})
  1466  })