github.com/jenspinney/cli@v6.42.1-0.20190207184520-7450c600020e+incompatible/cf/actors/routes_test.go (about)

     1  package actors_test
     2  
     3  import (
     4  	"errors"
     5  
     6  	. "code.cloudfoundry.org/cli/cf/actors"
     7  	"code.cloudfoundry.org/cli/cf/api/apifakes"
     8  	cferrors "code.cloudfoundry.org/cli/cf/errors"
     9  	"code.cloudfoundry.org/cli/cf/errors/errorsfakes"
    10  	"code.cloudfoundry.org/cli/cf/models"
    11  	"code.cloudfoundry.org/cli/cf/terminal/terminalfakes"
    12  	. "github.com/onsi/ginkgo"
    13  	. "github.com/onsi/gomega"
    14  )
    15  
    16  var _ = Describe("Routes", func() {
    17  	var (
    18  		fakeUI               *terminalfakes.FakeUI
    19  		fakeRouteRepository  *apifakes.FakeRouteRepository
    20  		fakeDomainRepository *apifakes.FakeDomainRepository
    21  		routeActor           RouteActor
    22  
    23  		expectedRoute  models.Route
    24  		expectedDomain models.DomainFields
    25  	)
    26  
    27  	BeforeEach(func() {
    28  		fakeUI = &terminalfakes.FakeUI{}
    29  		fakeRouteRepository = new(apifakes.FakeRouteRepository)
    30  		fakeDomainRepository = new(apifakes.FakeDomainRepository)
    31  		routeActor = NewRouteActor(fakeUI, fakeRouteRepository, fakeDomainRepository)
    32  	})
    33  
    34  	Describe("CreateRandomTCPRoute", func() {
    35  		BeforeEach(func() {
    36  			expectedDomain = models.DomainFields{
    37  				Name: "dies-tcp.com",
    38  			}
    39  
    40  			expectedRoute = models.Route{
    41  				GUID: "some-guid",
    42  			}
    43  
    44  			fakeRouteRepository.CreateReturns(expectedRoute, nil)
    45  		})
    46  
    47  		It("calls Create on the route repo", func() {
    48  			routeActor.CreateRandomTCPRoute(expectedDomain)
    49  
    50  			host, d, path, port, randomPort := fakeRouteRepository.CreateArgsForCall(0)
    51  			Expect(host).To(BeEmpty())
    52  			Expect(d).To(Equal(expectedDomain))
    53  			Expect(path).To(BeEmpty())
    54  			Expect(port).To(Equal(0))
    55  			Expect(randomPort).To(BeTrue())
    56  		})
    57  
    58  		It("states that a route is being created", func() {
    59  			routeActor.CreateRandomTCPRoute(expectedDomain)
    60  
    61  			Expect(fakeUI.SayCallCount()).To(Equal(1))
    62  			Expect(fakeUI.SayArgsForCall(0)).To(ContainSubstring("Creating random route for"))
    63  		})
    64  
    65  		It("returns the route retrieved from the repository", func() {
    66  			actualRoute, err := routeActor.CreateRandomTCPRoute(expectedDomain)
    67  			Expect(err).NotTo(HaveOccurred())
    68  
    69  			Expect(actualRoute).To(Equal(expectedRoute))
    70  		})
    71  
    72  		It("prints an error when creating the route fails", func() {
    73  			expectedError := errors.New("big bad error message")
    74  			fakeRouteRepository.CreateReturns(models.Route{}, expectedError)
    75  
    76  			actualRoute, err := routeActor.CreateRandomTCPRoute(expectedDomain)
    77  			Expect(err).To(Equal(expectedError))
    78  			Expect(actualRoute).To(Equal(models.Route{}))
    79  		})
    80  	})
    81  
    82  	Describe("FindOrCreateRoute", func() {
    83  		var (
    84  			expectedHostname string
    85  			expectedPath     string
    86  		)
    87  
    88  		BeforeEach(func() {
    89  			expectedHostname = "hostname"
    90  			expectedPath = "path"
    91  
    92  			expectedDomain = models.DomainFields{
    93  				Name:            "foo.com",
    94  				RouterGroupType: "tcp",
    95  			}
    96  
    97  			expectedRoute = models.Route{
    98  				Domain: expectedDomain,
    99  				Host:   expectedHostname,
   100  				Path:   expectedPath,
   101  			}
   102  		})
   103  
   104  		Context("the route exists", func() {
   105  			BeforeEach(func() {
   106  				fakeRouteRepository.FindReturns(expectedRoute, nil)
   107  			})
   108  
   109  			It("does not create a route", func() {
   110  				route, err := routeActor.FindOrCreateRoute(expectedHostname, expectedDomain, expectedPath, 0, false)
   111  				Expect(route).To(Equal(expectedRoute))
   112  				Expect(err).ToNot(HaveOccurred())
   113  
   114  				Expect(fakeRouteRepository.CreateCallCount()).To(Equal(0))
   115  
   116  				Expect(fakeUI.SayCallCount()).To(Equal(1))
   117  				output, _ := fakeUI.SayArgsForCall(0)
   118  				Expect(output).To(MatchRegexp("Using route.*hostname.foo.com/path"))
   119  			})
   120  		})
   121  
   122  		Context("the route does not exist", func() {
   123  			BeforeEach(func() {
   124  				fakeRouteRepository.FindReturns(models.Route{}, cferrors.NewModelNotFoundError("foo", "bar"))
   125  			})
   126  
   127  			Context("with a random port", func() {
   128  				var tcpRoute models.Route
   129  
   130  				BeforeEach(func() {
   131  					tcpRoute = models.Route{Port: 4}
   132  					fakeRouteRepository.CreateReturns(tcpRoute, nil)
   133  				})
   134  
   135  				It("creates a route with a TCP Route", func() {
   136  					route, err := routeActor.FindOrCreateRoute("", expectedDomain, "", 0, true)
   137  					Expect(route).To(Equal(tcpRoute))
   138  					Expect(err).ToNot(HaveOccurred())
   139  
   140  					Expect(fakeRouteRepository.CreateCallCount()).To(Equal(1))
   141  					hostname, domain, path, port, randomPort := fakeRouteRepository.CreateArgsForCall(0)
   142  					Expect(hostname).To(BeEmpty())
   143  					Expect(domain).To(Equal(expectedDomain))
   144  					Expect(path).To(BeEmpty())
   145  					Expect(port).To(Equal(0))
   146  					Expect(randomPort).To(BeTrue())
   147  
   148  					Expect(fakeUI.SayCallCount()).To(Equal(2))
   149  					output, _ := fakeUI.SayArgsForCall(0)
   150  					Expect(output).To(MatchRegexp("Creating random route for"))
   151  				})
   152  			})
   153  
   154  			Context("without a specific port", func() {
   155  				BeforeEach(func() {
   156  					fakeRouteRepository.CreateReturns(expectedRoute, nil)
   157  				})
   158  
   159  				It("creates a route ", func() {
   160  					route, err := routeActor.FindOrCreateRoute(expectedHostname, expectedDomain, "", 1337, false)
   161  					Expect(route).To(Equal(expectedRoute))
   162  					Expect(err).ToNot(HaveOccurred())
   163  
   164  					Expect(fakeRouteRepository.CreateCallCount()).To(Equal(1))
   165  					hostname, domain, path, port, randomPort := fakeRouteRepository.CreateArgsForCall(0)
   166  					Expect(hostname).To(Equal(expectedHostname))
   167  					Expect(domain).To(Equal(expectedDomain))
   168  					Expect(path).To(Equal(""))
   169  					Expect(port).To(Equal(1337))
   170  					Expect(randomPort).To(BeFalse())
   171  
   172  					Expect(fakeUI.SayCallCount()).To(Equal(2))
   173  					output, _ := fakeUI.SayArgsForCall(0)
   174  					Expect(output).To(MatchRegexp("Creating route.*hostname.foo.com:1337"))
   175  				})
   176  			})
   177  
   178  			Context("with a path", func() {
   179  				BeforeEach(func() {
   180  					fakeRouteRepository.CreateReturns(expectedRoute, nil)
   181  				})
   182  
   183  				It("creates a route ", func() {
   184  					route, err := routeActor.FindOrCreateRoute(expectedHostname, expectedDomain, expectedPath, 0, false)
   185  					Expect(route).To(Equal(expectedRoute))
   186  					Expect(err).ToNot(HaveOccurred())
   187  
   188  					Expect(fakeRouteRepository.CreateCallCount()).To(Equal(1))
   189  					hostname, domain, path, port, randomPort := fakeRouteRepository.CreateArgsForCall(0)
   190  					Expect(hostname).To(Equal(expectedHostname))
   191  					Expect(domain).To(Equal(expectedDomain))
   192  					Expect(path).To(Equal(expectedPath))
   193  					Expect(port).To(Equal(0))
   194  					Expect(randomPort).To(BeFalse())
   195  
   196  					Expect(fakeUI.SayCallCount()).To(Equal(2))
   197  					output, _ := fakeUI.SayArgsForCall(0)
   198  					Expect(output).To(MatchRegexp("Creating route.*hostname.foo.com/path"))
   199  				})
   200  			})
   201  		})
   202  	})
   203  
   204  	Describe("BindRoute", func() {
   205  		var (
   206  			expectedApp models.Application
   207  		)
   208  
   209  		BeforeEach(func() {
   210  			expectedRoute = models.Route{
   211  				GUID: "route-guid",
   212  			}
   213  			expectedApp = models.Application{
   214  				ApplicationFields: models.ApplicationFields{
   215  					Name: "app-name",
   216  					GUID: "app-guid",
   217  				},
   218  			}
   219  		})
   220  
   221  		Context("when the app has the route", func() {
   222  			BeforeEach(func() {
   223  				routeSummary := models.RouteSummary{
   224  					GUID: expectedRoute.GUID,
   225  				}
   226  				expectedApp.Routes = append(expectedApp.Routes, routeSummary)
   227  			})
   228  
   229  			It("does nothing", func() {
   230  				err := routeActor.BindRoute(expectedApp, expectedRoute)
   231  				Expect(err).To(BeNil())
   232  
   233  				Expect(fakeRouteRepository.BindCallCount()).To(Equal(0))
   234  			})
   235  		})
   236  
   237  		Context("when the app does not have a route", func() {
   238  			It("binds the route", func() {
   239  				err := routeActor.BindRoute(expectedApp, expectedRoute)
   240  				Expect(err).To(BeNil())
   241  
   242  				Expect(fakeRouteRepository.BindCallCount()).To(Equal(1))
   243  				routeGUID, appGUID := fakeRouteRepository.BindArgsForCall(0)
   244  				Expect(routeGUID).To(Equal(expectedRoute.GUID))
   245  				Expect(appGUID).To(Equal(expectedApp.ApplicationFields.GUID))
   246  
   247  				Expect(fakeUI.SayArgsForCall(0)).To(MatchRegexp("Binding .* to .*app-name"))
   248  				Expect(fakeUI.OkCallCount()).To(Equal(1))
   249  			})
   250  
   251  			Context("when the route is already in use", func() {
   252  				var expectedErr *errorsfakes.FakeHTTPError
   253  				BeforeEach(func() {
   254  					expectedErr = new(errorsfakes.FakeHTTPError)
   255  					expectedErr.ErrorCodeReturns(cferrors.InvalidRelation)
   256  					fakeRouteRepository.BindReturns(expectedErr)
   257  				})
   258  
   259  				It("outputs the error", func() {
   260  					err := routeActor.BindRoute(expectedApp, expectedRoute)
   261  					Expect(err.Error()).To(MatchRegexp("The route *. is already in use"))
   262  				})
   263  			})
   264  		})
   265  	})
   266  
   267  	Describe("UnbindAll", func() {
   268  		var app models.Application
   269  
   270  		BeforeEach(func() {
   271  			app = models.Application{
   272  				ApplicationFields: models.ApplicationFields{
   273  					GUID: "my-app-guid",
   274  				},
   275  				Routes: []models.RouteSummary{
   276  					{
   277  						GUID:   "my-route-guid-1",
   278  						Domain: models.DomainFields{Name: "mydomain1.com"},
   279  					},
   280  					{
   281  						GUID:   "my-route-guid-2",
   282  						Domain: models.DomainFields{Name: "mydomain2.com"},
   283  					},
   284  				},
   285  			}
   286  		})
   287  
   288  		Context("when unbinding does not work", func() {
   289  			var expectedError error
   290  
   291  			BeforeEach(func() {
   292  				expectedError = errors.New("ZOHMYGOD DUN BROKE")
   293  				fakeRouteRepository.UnbindReturns(expectedError)
   294  			})
   295  
   296  			It("returns the error immediately", func() {
   297  				err := routeActor.UnbindAll(app)
   298  				Expect(err).To(Equal(expectedError))
   299  
   300  				Expect(fakeRouteRepository.UnbindCallCount()).To(Equal(1))
   301  			})
   302  		})
   303  
   304  		Context("when unbinding works", func() {
   305  			It("unbinds the route for the app", func() {
   306  				err := routeActor.UnbindAll(app)
   307  				Expect(err).NotTo(HaveOccurred())
   308  
   309  				Expect(fakeRouteRepository.UnbindCallCount()).To(Equal(2))
   310  
   311  				routeGUID, appGUID := fakeRouteRepository.UnbindArgsForCall(0)
   312  				Expect(routeGUID).To(Equal("my-route-guid-1"))
   313  				Expect(appGUID).To(Equal("my-app-guid"))
   314  
   315  				routeGUID, appGUID = fakeRouteRepository.UnbindArgsForCall(1)
   316  				Expect(routeGUID).To(Equal("my-route-guid-2"))
   317  				Expect(appGUID).To(Equal("my-app-guid"))
   318  
   319  				Expect(fakeUI.SayCallCount()).To(Equal(2))
   320  
   321  				message, _ := fakeUI.SayArgsForCall(0)
   322  				Expect(message).To(ContainSubstring("Removing route"))
   323  
   324  				message, _ = fakeUI.SayArgsForCall(1)
   325  				Expect(message).To(ContainSubstring("Removing route"))
   326  			})
   327  		})
   328  	})
   329  
   330  	Describe("FindDomain", func() {
   331  		var (
   332  			routeName           string
   333  			hostname            string
   334  			domain              models.DomainFields
   335  			findDomainErr       error
   336  			domainNotFoundError error
   337  		)
   338  
   339  		BeforeEach(func() {
   340  			routeName = "my-hostname.my-domain.com"
   341  			domainNotFoundError = cferrors.NewModelNotFoundError("Domain", routeName)
   342  		})
   343  
   344  		JustBeforeEach(func() {
   345  			hostname, domain, findDomainErr = routeActor.FindDomain(routeName)
   346  		})
   347  		Context("when the route belongs to a private domain", func() {
   348  			Context("and do not have a hostname", func() {
   349  				var privateDomain models.DomainFields
   350  
   351  				BeforeEach(func() {
   352  					routeName = "my-domain.com"
   353  					privateDomain = models.DomainFields{
   354  						GUID: "private-domain-guid",
   355  					}
   356  					fakeDomainRepository.FindPrivateByNameReturns(privateDomain, nil)
   357  				})
   358  
   359  				It("returns the private domain", func() {
   360  					Expect(findDomainErr).NotTo(HaveOccurred())
   361  					Expect(fakeDomainRepository.FindPrivateByNameCallCount()).To(Equal(1))
   362  					Expect(fakeDomainRepository.FindPrivateByNameArgsForCall(0)).To(Equal("my-domain.com"))
   363  					Expect(hostname).To(Equal(""))
   364  					Expect(domain).To(Equal(privateDomain))
   365  				})
   366  			})
   367  
   368  			Context("and have a hostname", func() {
   369  				var privateDomain models.DomainFields
   370  
   371  				BeforeEach(func() {
   372  					routeName = "my-hostname.my-domain.com"
   373  					privateDomain = models.DomainFields{
   374  						GUID: "private-domain-guid",
   375  					}
   376  					fakeDomainRepository.FindPrivateByNameStub = func(name string) (models.DomainFields, error) {
   377  						if name == "my-domain.com" {
   378  							return privateDomain, nil
   379  						}
   380  						return models.DomainFields{}, domainNotFoundError
   381  					}
   382  				})
   383  
   384  				It("returns the private domain", func() {
   385  					Expect(findDomainErr).NotTo(HaveOccurred())
   386  					Expect(fakeDomainRepository.FindPrivateByNameCallCount()).To(Equal(2))
   387  					Expect(fakeDomainRepository.FindPrivateByNameArgsForCall(0)).To(Equal("my-hostname.my-domain.com"))
   388  					Expect(hostname).To(Equal("my-hostname"))
   389  					Expect(domain).To(Equal(privateDomain))
   390  				})
   391  			})
   392  		})
   393  		Context("when the route belongs to a shared domain", func() {
   394  			var (
   395  				sharedDomain models.DomainFields
   396  			)
   397  
   398  			BeforeEach(func() {
   399  				sharedDomain = models.DomainFields{
   400  					GUID: "shared-domain-guid",
   401  				}
   402  				fakeDomainRepository.FindPrivateByNameStub = func(name string) (models.DomainFields, error) {
   403  					return models.DomainFields{}, domainNotFoundError
   404  				}
   405  			})
   406  
   407  			Context("when the route has no hostname", func() {
   408  				BeforeEach(func() {
   409  					fakeDomainRepository.FindSharedByNameStub = func(name string) (models.DomainFields, error) {
   410  						if name == "my-hostname.my-domain.com" {
   411  							return sharedDomain, nil
   412  						}
   413  						return models.DomainFields{}, domainNotFoundError
   414  					}
   415  				})
   416  
   417  				It("returns the shared domain", func() {
   418  					Expect(findDomainErr).NotTo(HaveOccurred())
   419  					Expect(fakeDomainRepository.FindPrivateByNameCallCount()).To(Equal(2))
   420  					Expect(fakeDomainRepository.FindSharedByNameCallCount()).To(Equal(1))
   421  					Expect(fakeDomainRepository.FindSharedByNameArgsForCall(0)).To(Equal("my-hostname.my-domain.com"))
   422  					Expect(hostname).To(Equal(""))
   423  					Expect(domain).To(Equal(sharedDomain))
   424  				})
   425  			})
   426  
   427  			Context("when the route has a hostname", func() {
   428  				BeforeEach(func() {
   429  					fakeDomainRepository.FindSharedByNameStub = func(name string) (models.DomainFields, error) {
   430  						if name == "my-domain.com" {
   431  							return sharedDomain, nil
   432  						}
   433  						return models.DomainFields{}, domainNotFoundError
   434  					}
   435  				})
   436  
   437  				It("returns the shared domain and hostname", func() {
   438  					Expect(findDomainErr).NotTo(HaveOccurred())
   439  					Expect(fakeDomainRepository.FindPrivateByNameCallCount()).To(Equal(2))
   440  					Expect(fakeDomainRepository.FindSharedByNameCallCount()).To(Equal(2))
   441  					Expect(fakeDomainRepository.FindSharedByNameArgsForCall(0)).To(Equal("my-hostname.my-domain.com"))
   442  					Expect(fakeDomainRepository.FindSharedByNameArgsForCall(1)).To(Equal("my-domain.com"))
   443  					Expect(hostname).To(Equal("my-hostname"))
   444  					Expect(domain).To(Equal(sharedDomain))
   445  				})
   446  			})
   447  		})
   448  
   449  		Context("when the route does not belong to any existing domains", func() {
   450  			BeforeEach(func() {
   451  				routeName = "non-existant-domain.com"
   452  				fakeDomainRepository.FindPrivateByNameReturns(models.DomainFields{}, domainNotFoundError)
   453  				fakeDomainRepository.FindSharedByNameReturns(models.DomainFields{}, domainNotFoundError)
   454  			})
   455  
   456  			It("returns an error", func() {
   457  				Expect(findDomainErr).To(HaveOccurred())
   458  				Expect(findDomainErr.Error()).To(Equal("The route non-existant-domain.com did not match any existing domains."))
   459  			})
   460  		})
   461  	})
   462  
   463  	Describe("FindPath", func() {
   464  		Context("when there is a path", func() {
   465  			It("returns the route without path and the path", func() {
   466  				routeName := "host.domain/long/path"
   467  				route, path := routeActor.FindPath(routeName)
   468  				Expect(route).To(Equal("host.domain"))
   469  				Expect(path).To(Equal("long/path"))
   470  			})
   471  		})
   472  
   473  		Context("when there is no path", func() {
   474  			It("returns the route path and the empty string", func() {
   475  				routeName := "host.domain"
   476  				route, path := routeActor.FindPath(routeName)
   477  				Expect(route).To(Equal("host.domain"))
   478  				Expect(path).To(Equal(""))
   479  			})
   480  		})
   481  	})
   482  
   483  	Describe("FindPort", func() {
   484  		Context("when there is a port", func() {
   485  			It("returns the route without port and the port", func() {
   486  				routeName := "host.domain:12345"
   487  				route, port, err := routeActor.FindPort(routeName)
   488  				Expect(route).To(Equal("host.domain"))
   489  				Expect(port).To(Equal(12345))
   490  				Expect(err).NotTo(HaveOccurred())
   491  			})
   492  		})
   493  
   494  		Context("when there is no port", func() {
   495  			It("returns the route port and invalid port", func() {
   496  				routeName := "host.domain"
   497  				route, port, err := routeActor.FindPort(routeName)
   498  				Expect(route).To(Equal("host.domain"))
   499  				Expect(port).To(Equal(0))
   500  				Expect(err).NotTo(HaveOccurred())
   501  			})
   502  		})
   503  
   504  		Context("when there is an invalid port", func() {
   505  			It("returns an error", func() {
   506  				routeName := "host.domain:thisisnotaport"
   507  				_, _, err := routeActor.FindPort(routeName)
   508  				Expect(err).To(HaveOccurred())
   509  			})
   510  		})
   511  	})
   512  
   513  	Describe("FindAndBindRoute", func() {
   514  		var (
   515  			routeName            string
   516  			findAndBindRouteErr  error
   517  			appParamsFromContext models.AppParams
   518  		)
   519  
   520  		BeforeEach(func() {
   521  			appParamsFromContext = models.AppParams{}
   522  		})
   523  
   524  		JustBeforeEach(func() {
   525  			appName := "app-name"
   526  			findAndBindRouteErr = routeActor.FindAndBindRoute(
   527  				routeName,
   528  				models.Application{
   529  					ApplicationFields: models.ApplicationFields{
   530  						Name: appName,
   531  						GUID: "app-guid",
   532  					},
   533  				},
   534  				appParamsFromContext,
   535  			)
   536  		})
   537  
   538  		Context("when the route is a HTTP route", func() {
   539  			var httpDomain models.DomainFields
   540  
   541  			BeforeEach(func() {
   542  				httpDomain = models.DomainFields{
   543  					Name: "domain.com",
   544  					GUID: "domain-guid",
   545  				}
   546  				domainNotFoundError := cferrors.NewModelNotFoundError("Domain", "some-domain.com")
   547  
   548  				fakeDomainRepository.FindPrivateByNameReturns(models.DomainFields{}, domainNotFoundError)
   549  				fakeDomainRepository.FindSharedByNameStub = func(name string) (models.DomainFields, error) {
   550  					if name == "domain.com" {
   551  						return httpDomain, nil
   552  					}
   553  					return models.DomainFields{}, domainNotFoundError
   554  				}
   555  			})
   556  
   557  			Context("contains a port", func() {
   558  				BeforeEach(func() {
   559  					routeName = "domain.com:3333"
   560  				})
   561  
   562  				It("should return an error", func() {
   563  					Expect(findAndBindRouteErr).To(HaveOccurred())
   564  					Expect(findAndBindRouteErr.Error()).To(Equal("Port not allowed in HTTP route domain.com"))
   565  				})
   566  			})
   567  
   568  			Context("does not contain a port", func() {
   569  				BeforeEach(func() {
   570  					routeName = "host.domain.com"
   571  
   572  					fakeRouteRepository.FindReturns(models.Route{}, cferrors.NewModelNotFoundError("Route", "some-route"))
   573  					fakeRouteRepository.CreateReturns(
   574  						models.Route{
   575  							GUID:   "route-guid",
   576  							Domain: httpDomain,
   577  							Path:   "path",
   578  						},
   579  						nil,
   580  					)
   581  					fakeRouteRepository.BindReturns(nil)
   582  				})
   583  
   584  				It("creates and binds the route", func() {
   585  					Expect(findAndBindRouteErr).NotTo(HaveOccurred())
   586  
   587  					actualDomainName := fakeDomainRepository.FindSharedByNameArgsForCall(1)
   588  					Expect(actualDomainName).To(Equal("domain.com"))
   589  
   590  					actualHost, actualDomain, actualPath, actualPort := fakeRouteRepository.FindArgsForCall(0)
   591  					Expect(actualHost).To(Equal("host"))
   592  					Expect(actualDomain).To(Equal(httpDomain))
   593  					Expect(actualPath).To(Equal(""))
   594  					Expect(actualPort).To(Equal(0))
   595  
   596  					actualHost, actualDomain, actualPath, actualPort, actualUseRandomPort := fakeRouteRepository.CreateArgsForCall(0)
   597  					Expect(actualHost).To(Equal("host"))
   598  					Expect(actualDomain).To(Equal(httpDomain))
   599  					Expect(actualPath).To(Equal(""))
   600  					Expect(actualPort).To(Equal(0))
   601  					Expect(actualUseRandomPort).To(BeFalse())
   602  
   603  					routeGUID, appGUID := fakeRouteRepository.BindArgsForCall(0)
   604  					Expect(routeGUID).To(Equal("route-guid"))
   605  					Expect(appGUID).To(Equal("app-guid"))
   606  				})
   607  
   608  				Context("contains a path", func() {
   609  					BeforeEach(func() {
   610  						routeName = "host.domain.com/path"
   611  					})
   612  
   613  					It("creates and binds the route", func() {
   614  						Expect(findAndBindRouteErr).NotTo(HaveOccurred())
   615  
   616  						actualDomainName := fakeDomainRepository.FindSharedByNameArgsForCall(1)
   617  						Expect(actualDomainName).To(Equal("domain.com"))
   618  
   619  						actualHost, actualDomain, actualPath, actualPort := fakeRouteRepository.FindArgsForCall(0)
   620  						Expect(actualHost).To(Equal("host"))
   621  						Expect(actualDomain).To(Equal(httpDomain))
   622  						Expect(actualPath).To(Equal("path"))
   623  						Expect(actualPort).To(Equal(0))
   624  
   625  						actualHost, actualDomain, actualPath, actualPort, actualUseRandomPort := fakeRouteRepository.CreateArgsForCall(0)
   626  						Expect(actualHost).To(Equal("host"))
   627  						Expect(actualDomain).To(Equal(httpDomain))
   628  						Expect(actualPath).To(Equal("path"))
   629  						Expect(actualPort).To(Equal(0))
   630  						Expect(actualUseRandomPort).To(BeFalse())
   631  
   632  						routeGUID, appGUID := fakeRouteRepository.BindArgsForCall(0)
   633  						Expect(routeGUID).To(Equal("route-guid"))
   634  						Expect(appGUID).To(Equal("app-guid"))
   635  					})
   636  				})
   637  			})
   638  
   639  			Context("the --hostname flag is provided", func() {
   640  				BeforeEach(func() {
   641  					appParamsFromContext = models.AppParams{
   642  						Hosts: []string{"flag-hostname"},
   643  					}
   644  				})
   645  
   646  				Context("the route contains a hostname", func() {
   647  					BeforeEach(func() {
   648  						routeName = "host.domain.com/path"
   649  					})
   650  
   651  					It("should replace only the hostname", func() {
   652  						Expect(findAndBindRouteErr).NotTo(HaveOccurred())
   653  
   654  						actualHost, actualDomain, actualPath, actualPort := fakeRouteRepository.FindArgsForCall(0)
   655  						Expect(actualHost).To(Equal("flag-hostname"))
   656  						Expect(actualDomain).To(Equal(httpDomain))
   657  						Expect(actualPath).To(Equal("path"))
   658  						Expect(actualPort).To(Equal(0))
   659  					})
   660  				})
   661  
   662  				Context("the route does not contain a hostname", func() {
   663  					BeforeEach(func() {
   664  						routeName = "domain.com"
   665  					})
   666  
   667  					It("should set only the hostname", func() {
   668  						Expect(findAndBindRouteErr).NotTo(HaveOccurred())
   669  
   670  						actualHost, actualDomain, actualPath, actualPort := fakeRouteRepository.FindArgsForCall(0)
   671  						Expect(actualHost).To(Equal("flag-hostname"))
   672  						Expect(actualDomain).To(Equal(httpDomain))
   673  						Expect(actualPath).To(Equal(""))
   674  						Expect(actualPort).To(Equal(0))
   675  					})
   676  				})
   677  			})
   678  		})
   679  
   680  		Context("when -d domains is set", func() {
   681  			BeforeEach(func() {
   682  				appParamsFromContext = models.AppParams{
   683  					Domains: []string{"shared-domain.com"},
   684  				}
   685  			})
   686  
   687  			Context("it is a http shared domain", func() {
   688  				BeforeEach(func() {
   689  					httpDomain := models.DomainFields{
   690  						Name:            "shared-domain.com",
   691  						GUID:            "shared-domain-guid",
   692  						RouterGroupType: "",
   693  						Shared:          true,
   694  					}
   695  					domainNotFoundError := cferrors.NewModelNotFoundError("Domain", "some-domain.com")
   696  
   697  					fakeDomainRepository.FindPrivateByNameReturns(models.DomainFields{}, domainNotFoundError)
   698  					fakeDomainRepository.FindSharedByNameStub = func(name string) (models.DomainFields, error) {
   699  						if name == "shared-domain.com" {
   700  							return httpDomain, nil
   701  						}
   702  						return models.DomainFields{}, domainNotFoundError
   703  					}
   704  
   705  					fakeRouteRepository.FindReturns(models.Route{}, cferrors.NewModelNotFoundError("", ""))
   706  				})
   707  
   708  				Context("when the hostname is present in the original route", func() {
   709  					BeforeEach(func() {
   710  						routeName = "hostname.old-domain.com/path"
   711  					})
   712  
   713  					It("replace the domain from manifest", func() {
   714  						Expect(findAndBindRouteErr).NotTo(HaveOccurred())
   715  
   716  						Expect(fakeRouteRepository.FindCallCount()).To(Equal(1))
   717  
   718  						Expect(fakeRouteRepository.CreateCallCount()).To(Equal(1))
   719  						actualHost, actualDomain, actualPath, actualPort, actualUseRandomPort := fakeRouteRepository.CreateArgsForCall(0)
   720  						Expect(actualHost).To(Equal("hostname"))
   721  						Expect(actualDomain.Name).To(Equal("shared-domain.com"))
   722  						Expect(actualPath).To(Equal("path"))
   723  						Expect(actualPort).To(Equal(0))
   724  						Expect(actualUseRandomPort).To(BeFalse())
   725  					})
   726  				})
   727  
   728  				Context("when the hostname is provided as a flag", func() {
   729  					BeforeEach(func() {
   730  						routeName = "old-domain.com/path"
   731  						appParamsFromContext = models.AppParams{
   732  							Domains: []string{"shared-domain.com"},
   733  							Hosts:   []string{"hostname"},
   734  						}
   735  					})
   736  
   737  					It("replace the domain from manifest", func() {
   738  						Expect(findAndBindRouteErr).NotTo(HaveOccurred())
   739  
   740  						Expect(fakeRouteRepository.FindCallCount()).To(Equal(1))
   741  
   742  						Expect(fakeRouteRepository.CreateCallCount()).To(Equal(1))
   743  						actualHost, actualDomain, actualPath, actualPort, actualUseRandomPort := fakeRouteRepository.CreateArgsForCall(0)
   744  						Expect(actualHost).To(Equal("hostname"))
   745  						Expect(actualDomain.Name).To(Equal("shared-domain.com"))
   746  						Expect(actualPath).To(Equal("path"))
   747  						Expect(actualPort).To(Equal(0))
   748  						Expect(actualUseRandomPort).To(BeFalse())
   749  					})
   750  				})
   751  
   752  				Context("when the path is provided as a flag", func() {
   753  					BeforeEach(func() {
   754  						routeName = "hostname.old-domain.com/oldpath"
   755  						path := "path"
   756  						appParamsFromContext = models.AppParams{
   757  							Domains:   []string{"shared-domain.com"},
   758  							RoutePath: &path,
   759  						}
   760  					})
   761  
   762  					It("replace the domain and path from manifest", func() {
   763  						Expect(findAndBindRouteErr).NotTo(HaveOccurred())
   764  
   765  						Expect(fakeRouteRepository.FindCallCount()).To(Equal(1))
   766  
   767  						Expect(fakeRouteRepository.CreateCallCount()).To(Equal(1))
   768  						actualHost, actualDomain, actualPath, actualPort, actualUseRandomPort := fakeRouteRepository.CreateArgsForCall(0)
   769  						Expect(actualHost).To(Equal("hostname"))
   770  						Expect(actualDomain.Name).To(Equal("shared-domain.com"))
   771  						Expect(actualPath).To(Equal("path"))
   772  						Expect(actualPort).To(Equal(0))
   773  						Expect(actualUseRandomPort).To(BeFalse())
   774  					})
   775  				})
   776  			})
   777  
   778  			Context("when it is a private domain", func() {
   779  				BeforeEach(func() {
   780  					httpDomain := models.DomainFields{
   781  						Name:            "private-domain.com",
   782  						GUID:            "private-domain-guid",
   783  						RouterGroupType: "",
   784  					}
   785  
   786  					fakeDomainRepository.FindPrivateByNameReturns(httpDomain, nil)
   787  
   788  					fakeRouteRepository.FindReturns(models.Route{}, cferrors.NewModelNotFoundError("", ""))
   789  					routeName = "hostname.old-domain.com/path"
   790  					appParamsFromContext = models.AppParams{
   791  						Domains: []string{"private-domain.com"},
   792  					}
   793  				})
   794  
   795  				It("replace the domain from manifest", func() {
   796  					Expect(findAndBindRouteErr).NotTo(HaveOccurred())
   797  
   798  					Expect(fakeRouteRepository.FindCallCount()).To(Equal(1))
   799  
   800  					Expect(fakeRouteRepository.CreateCallCount()).To(Equal(1))
   801  					actualHost, actualDomain, actualPath, actualPort, actualUseRandomPort := fakeRouteRepository.CreateArgsForCall(0)
   802  					Expect(actualHost).To(BeEmpty())
   803  					Expect(actualDomain.Name).To(Equal("private-domain.com"))
   804  					Expect(actualPath).To(Equal("path"))
   805  					Expect(actualPort).To(BeZero())
   806  					Expect(actualUseRandomPort).To(BeFalse())
   807  				})
   808  			})
   809  		})
   810  
   811  		Context("the --random-route flag is provided", func() {
   812  			BeforeEach(func() {
   813  				appParamsFromContext = models.AppParams{
   814  					UseRandomRoute: true,
   815  				}
   816  
   817  				fakeRouteRepository.FindReturns(models.Route{}, cferrors.NewModelNotFoundError("Route", "tcp-domain.com:3333"))
   818  			})
   819  
   820  			Context("it is a http route", func() {
   821  				var httpDomain models.DomainFields
   822  
   823  				BeforeEach(func() {
   824  					httpDomain = models.DomainFields{
   825  						Name: "domain.com",
   826  						GUID: "domain-guid",
   827  					}
   828  					domainNotFoundError := cferrors.NewModelNotFoundError("Domain", "some-domain.com")
   829  
   830  					fakeDomainRepository.FindPrivateByNameReturns(models.DomainFields{}, domainNotFoundError)
   831  					fakeDomainRepository.FindSharedByNameStub = func(name string) (models.DomainFields, error) {
   832  						if name == "domain.com" {
   833  							return httpDomain, nil
   834  						}
   835  						return models.DomainFields{}, domainNotFoundError
   836  					}
   837  				})
   838  
   839  				Context("the route does not have a hostname", func() {
   840  					BeforeEach(func() {
   841  						routeName = "domain.com/path"
   842  					})
   843  					It("should append a random name ", func() {
   844  						Expect(findAndBindRouteErr).NotTo(HaveOccurred())
   845  
   846  						actualHost, actualDomain, actualPath, actualPort := fakeRouteRepository.FindArgsForCall(0)
   847  						Expect(actualHost).To(MatchRegexp("[a-z]-[a-z]"))
   848  						Expect(actualDomain.Name).To(Equal("domain.com"))
   849  						Expect(actualPath).To(Equal("path"))
   850  						Expect(actualPort).To(Equal(0))
   851  						actualHost, actualDomain, actualPath, actualPort, useRandomPort := fakeRouteRepository.CreateArgsForCall(0)
   852  						Expect(actualHost).To(MatchRegexp("[a-z]-[a-z]"))
   853  						Expect(actualDomain.Name).To(Equal("domain.com"))
   854  						Expect(actualPath).To(Equal("path"))
   855  						Expect(actualPort).To(Equal(0))
   856  						Expect(useRandomPort).To(BeFalse())
   857  					})
   858  				})
   859  
   860  				Context("the route has a hostname", func() {
   861  					BeforeEach(func() {
   862  						routeName = "host.domain.com/path"
   863  					})
   864  					It("should replace the hostname with a random name", func() {
   865  						Expect(findAndBindRouteErr).NotTo(HaveOccurred())
   866  
   867  						actualHost, actualDomain, actualPath, actualPort := fakeRouteRepository.FindArgsForCall(0)
   868  						Expect(actualHost).To(MatchRegexp("[a-z]-[a-z]"))
   869  						Expect(actualDomain.Name).To(Equal("domain.com"))
   870  						Expect(actualPath).To(Equal("path"))
   871  						Expect(actualPort).To(Equal(0))
   872  					})
   873  				})
   874  
   875  				Context("when --hostname flag is present", func() {
   876  					BeforeEach(func() {
   877  						appParamsFromContext = models.AppParams{
   878  							UseRandomRoute: true,
   879  							Hosts:          []string{"flag-hostname"},
   880  						}
   881  						routeName = "host.domain.com/path"
   882  
   883  					})
   884  
   885  					It("should replace the hostname with flag hostname", func() {
   886  						Expect(findAndBindRouteErr).NotTo(HaveOccurred())
   887  
   888  						actualHost, actualDomain, actualPath, actualPort := fakeRouteRepository.FindArgsForCall(0)
   889  						Expect(actualHost).To(Equal("flag-hostname"))
   890  						Expect(actualDomain.Name).To(Equal("domain.com"))
   891  						Expect(actualPath).To(Equal("path"))
   892  						Expect(actualPort).To(Equal(0))
   893  					})
   894  				})
   895  			})
   896  
   897  			Context("it is a tcp route", func() {
   898  				var tcpDomain models.DomainFields
   899  
   900  				BeforeEach(func() {
   901  					tcpDomain = models.DomainFields{
   902  						Name:            "tcp-domain.com",
   903  						GUID:            "tcp-domain-guid",
   904  						RouterGroupGUID: "tcp-guid",
   905  						RouterGroupType: "tcp",
   906  					}
   907  					domainNotFoundError := cferrors.NewModelNotFoundError("Domain", "some-domain.com")
   908  
   909  					fakeDomainRepository.FindPrivateByNameReturns(models.DomainFields{}, domainNotFoundError)
   910  					fakeDomainRepository.FindSharedByNameStub = func(name string) (models.DomainFields, error) {
   911  						if name == "tcp-domain.com" {
   912  							return tcpDomain, nil
   913  						}
   914  						return models.DomainFields{}, domainNotFoundError
   915  					}
   916  					routeName = "tcp-domain.com:3333"
   917  				})
   918  
   919  				It("replaces the provided port with a random port", func() {
   920  					Expect(findAndBindRouteErr).NotTo(HaveOccurred())
   921  					Expect(fakeRouteRepository.FindCallCount()).To(Equal(0))
   922  
   923  					actualHost, actualDomain, actualPath, actualPort, useRandomPort := fakeRouteRepository.CreateArgsForCall(0)
   924  					Expect(actualHost).To(Equal(""))
   925  					Expect(actualDomain.Name).To(Equal("tcp-domain.com"))
   926  					Expect(actualPath).To(Equal(""))
   927  					Expect(actualPort).To(Equal(0))
   928  					Expect(useRandomPort).To(Equal(true))
   929  				})
   930  			})
   931  		})
   932  
   933  		Context("the --route-path flag is provided", func() {
   934  			BeforeEach(func() {
   935  				path := "flag-routepath"
   936  				appParamsFromContext = models.AppParams{
   937  					RoutePath: &path,
   938  				}
   939  			})
   940  
   941  			Context("it is a http route", func() {
   942  				var httpDomain models.DomainFields
   943  
   944  				BeforeEach(func() {
   945  					httpDomain = models.DomainFields{
   946  						Name: "domain.com",
   947  						GUID: "domain-guid",
   948  					}
   949  					domainNotFoundError := cferrors.NewModelNotFoundError("Domain", "some-domain.com")
   950  
   951  					fakeDomainRepository.FindPrivateByNameReturns(models.DomainFields{}, domainNotFoundError)
   952  					fakeDomainRepository.FindSharedByNameStub = func(name string) (models.DomainFields, error) {
   953  						if name == "domain.com" {
   954  							return httpDomain, nil
   955  						}
   956  						return models.DomainFields{}, domainNotFoundError
   957  					}
   958  				})
   959  
   960  				Context("it does not have a path", func() {
   961  					BeforeEach(func() {
   962  						routeName = "host.domain.com"
   963  					})
   964  
   965  					It("adds the path to the route", func() {
   966  						Expect(findAndBindRouteErr).NotTo(HaveOccurred())
   967  
   968  						actualHost, actualDomain, actualPath, actualPort := fakeRouteRepository.FindArgsForCall(0)
   969  						Expect(actualHost).To(Equal("host"))
   970  						Expect(actualDomain.Name).To(Equal("domain.com"))
   971  						Expect(actualPath).To(Equal("flag-routepath"))
   972  						Expect(actualPort).To(Equal(0))
   973  					})
   974  				})
   975  
   976  				Context("a path is already specified on the route", func() {
   977  					BeforeEach(func() {
   978  						routeName = "host.domain.com/path"
   979  					})
   980  
   981  					It("replaces the path on the route", func() {
   982  						Expect(findAndBindRouteErr).NotTo(HaveOccurred())
   983  
   984  						actualHost, actualDomain, actualPath, actualPort := fakeRouteRepository.FindArgsForCall(0)
   985  						Expect(actualHost).To(Equal("host"))
   986  						Expect(actualDomain.Name).To(Equal("domain.com"))
   987  						Expect(actualPath).To(Equal("flag-routepath"))
   988  						Expect(actualPort).To(Equal(0))
   989  					})
   990  				})
   991  			})
   992  
   993  			Context("it is a tcp route", func() {
   994  				var tcpDomain models.DomainFields
   995  
   996  				BeforeEach(func() {
   997  					tcpDomain = models.DomainFields{
   998  						Name:            "tcp-domain.com",
   999  						GUID:            "tcp-domain-guid",
  1000  						RouterGroupGUID: "tcp-guid",
  1001  						RouterGroupType: "tcp",
  1002  					}
  1003  					domainNotFoundError := cferrors.NewModelNotFoundError("Domain", "some-domain.com")
  1004  
  1005  					fakeDomainRepository.FindPrivateByNameReturns(models.DomainFields{}, domainNotFoundError)
  1006  					fakeDomainRepository.FindSharedByNameStub = func(name string) (models.DomainFields, error) {
  1007  						if name == "tcp-domain.com" {
  1008  							return tcpDomain, nil
  1009  						}
  1010  						return models.DomainFields{}, domainNotFoundError
  1011  					}
  1012  					routeName = "tcp-domain.com:3333"
  1013  				})
  1014  
  1015  				It("does not use the flag", func() {
  1016  					Expect(findAndBindRouteErr).NotTo(HaveOccurred())
  1017  
  1018  					actualHost, actualDomain, actualPath, actualPort := fakeRouteRepository.FindArgsForCall(0)
  1019  					Expect(actualHost).To(Equal(""))
  1020  					Expect(actualDomain.Name).To(Equal("tcp-domain.com"))
  1021  					Expect(actualPath).To(Equal(""))
  1022  					Expect(actualPort).To(Equal(3333))
  1023  				})
  1024  			})
  1025  		})
  1026  
  1027  		Context("when the route is a TCP route", func() {
  1028  			var tcpDomain models.DomainFields
  1029  
  1030  			BeforeEach(func() {
  1031  				tcpDomain = models.DomainFields{
  1032  					Name:            "tcp-domain.com",
  1033  					GUID:            "tcp-domain-guid",
  1034  					RouterGroupGUID: "tcp-guid",
  1035  					RouterGroupType: "tcp",
  1036  				}
  1037  				domainNotFoundError := cferrors.NewModelNotFoundError("Domain", "some-domain.com")
  1038  
  1039  				fakeDomainRepository.FindPrivateByNameReturns(models.DomainFields{}, domainNotFoundError)
  1040  				fakeDomainRepository.FindSharedByNameStub = func(name string) (models.DomainFields, error) {
  1041  					if name == "tcp-domain.com" {
  1042  						return tcpDomain, nil
  1043  					}
  1044  					return models.DomainFields{}, domainNotFoundError
  1045  				}
  1046  			})
  1047  
  1048  			Context("contains a path", func() {
  1049  				BeforeEach(func() {
  1050  					routeName = "tcp-domain.com:3333/path"
  1051  				})
  1052  
  1053  				It("returns an error", func() {
  1054  					Expect(findAndBindRouteErr).To(HaveOccurred())
  1055  					Expect(findAndBindRouteErr.Error()).To(Equal("Path not allowed in TCP route tcp-domain.com"))
  1056  				})
  1057  			})
  1058  
  1059  			Context("does not contain a path", func() {
  1060  				BeforeEach(func() {
  1061  					routeName = "tcp-domain.com:3333"
  1062  
  1063  					fakeRouteRepository.FindReturns(models.Route{}, cferrors.NewModelNotFoundError("Route", "some-route"))
  1064  					fakeRouteRepository.CreateReturns(
  1065  						models.Route{
  1066  							GUID:   "route-guid",
  1067  							Domain: tcpDomain,
  1068  							Path:   "path",
  1069  						},
  1070  						nil,
  1071  					)
  1072  					fakeRouteRepository.BindReturns(nil)
  1073  				})
  1074  
  1075  				It("creates and binds the route", func() {
  1076  					Expect(findAndBindRouteErr).NotTo(HaveOccurred())
  1077  
  1078  					actualDomainName := fakeDomainRepository.FindSharedByNameArgsForCall(0)
  1079  					Expect(actualDomainName).To(Equal("tcp-domain.com"))
  1080  
  1081  					actualHost, actualDomain, actualPath, actualPort := fakeRouteRepository.FindArgsForCall(0)
  1082  					Expect(actualHost).To(Equal(""))
  1083  					Expect(actualDomain).To(Equal(tcpDomain))
  1084  					Expect(actualPath).To(Equal(""))
  1085  					Expect(actualPort).To(Equal(3333))
  1086  
  1087  					actualHost, actualDomain, actualPath, actualPort, actualUseRandomPort := fakeRouteRepository.CreateArgsForCall(0)
  1088  					Expect(actualHost).To(Equal(""))
  1089  					Expect(actualDomain).To(Equal(tcpDomain))
  1090  					Expect(actualPath).To(Equal(""))
  1091  					Expect(actualPort).To(Equal(3333))
  1092  					Expect(actualUseRandomPort).To(BeFalse())
  1093  
  1094  					routeGUID, appGUID := fakeRouteRepository.BindArgsForCall(0)
  1095  					Expect(routeGUID).To(Equal("route-guid"))
  1096  					Expect(appGUID).To(Equal("app-guid"))
  1097  				})
  1098  			})
  1099  
  1100  			Context("the --hostname flag is provided", func() {
  1101  				BeforeEach(func() {
  1102  					routeName = "tcp-domain.com:3333"
  1103  					appParamsFromContext = models.AppParams{
  1104  						Hosts: []string{"flag-hostname"},
  1105  					}
  1106  				})
  1107  
  1108  				It("should not change the route", func() {
  1109  					Expect(findAndBindRouteErr).NotTo(HaveOccurred())
  1110  
  1111  					actualHost, actualDomain, actualPath, actualPort := fakeRouteRepository.FindArgsForCall(0)
  1112  					Expect(actualHost).To(Equal(""))
  1113  					Expect(actualDomain).To(Equal(tcpDomain))
  1114  					Expect(actualPath).To(Equal(""))
  1115  					Expect(actualPort).To(Equal(3333))
  1116  				})
  1117  			})
  1118  		})
  1119  	})
  1120  })