github.com/loggregator/cli@v6.33.1-0.20180224010324-82334f081791+incompatible/cf/commands/route/create_route_test.go (about)

     1  package route_test
     2  
     3  import (
     4  	"errors"
     5  
     6  	"code.cloudfoundry.org/cli/cf/commandregistry"
     7  	"code.cloudfoundry.org/cli/cf/commands/route"
     8  	"code.cloudfoundry.org/cli/cf/configuration/coreconfig"
     9  	"code.cloudfoundry.org/cli/cf/flags"
    10  	"code.cloudfoundry.org/cli/cf/models"
    11  	"code.cloudfoundry.org/cli/cf/requirements/requirementsfakes"
    12  	"github.com/blang/semver"
    13  
    14  	"code.cloudfoundry.org/cli/cf/api/apifakes"
    15  	"code.cloudfoundry.org/cli/cf/requirements"
    16  
    17  	testconfig "code.cloudfoundry.org/cli/util/testhelpers/configuration"
    18  	testterm "code.cloudfoundry.org/cli/util/testhelpers/terminal"
    19  
    20  	. "code.cloudfoundry.org/cli/util/testhelpers/matchers"
    21  
    22  	. "github.com/onsi/ginkgo"
    23  	. "github.com/onsi/gomega"
    24  )
    25  
    26  var _ = Describe("CreateRoute", func() {
    27  	var (
    28  		ui         *testterm.FakeUI
    29  		routeRepo  *apifakes.FakeRouteRepository
    30  		configRepo coreconfig.Repository
    31  
    32  		cmd         commandregistry.Command
    33  		deps        commandregistry.Dependency
    34  		factory     *requirementsfakes.FakeFactory
    35  		flagContext flags.FlagContext
    36  
    37  		spaceRequirement         *requirementsfakes.FakeSpaceRequirement
    38  		domainRequirement        *requirementsfakes.FakeDomainRequirement
    39  		minAPIVersionRequirement requirements.Requirement
    40  	)
    41  
    42  	BeforeEach(func() {
    43  		ui = &testterm.FakeUI{}
    44  		configRepo = testconfig.NewRepositoryWithDefaults()
    45  		routeRepo = new(apifakes.FakeRouteRepository)
    46  		repoLocator := deps.RepoLocator.SetRouteRepository(routeRepo)
    47  
    48  		deps = commandregistry.Dependency{
    49  			UI:          ui,
    50  			Config:      configRepo,
    51  			RepoLocator: repoLocator,
    52  		}
    53  
    54  		cmd = &route.CreateRoute{}
    55  		cmd.SetDependency(deps, false)
    56  
    57  		flagContext = flags.NewFlagContext(cmd.MetaData().Flags)
    58  
    59  		factory = new(requirementsfakes.FakeFactory)
    60  
    61  		spaceRequirement = new(requirementsfakes.FakeSpaceRequirement)
    62  		space := models.Space{}
    63  		space.GUID = "space-guid"
    64  		space.Name = "space-name"
    65  		spaceRequirement.GetSpaceReturns(space)
    66  		factory.NewSpaceRequirementReturns(spaceRequirement)
    67  
    68  		domainRequirement = new(requirementsfakes.FakeDomainRequirement)
    69  		domainRequirement.GetDomainReturns(models.DomainFields{
    70  			GUID: "domain-guid",
    71  			Name: "domain-name",
    72  		})
    73  		factory.NewDomainRequirementReturns(domainRequirement)
    74  
    75  		minAPIVersionRequirement = &passingRequirement{}
    76  		factory.NewMinAPIVersionRequirementReturns(minAPIVersionRequirement)
    77  	})
    78  
    79  	Describe("Requirements", func() {
    80  		Context("when not provided exactly two args", func() {
    81  			BeforeEach(func() {
    82  				err := flagContext.Parse("space-name")
    83  				Expect(err).NotTo(HaveOccurred())
    84  			})
    85  
    86  			It("fails with usage", func() {
    87  				_, err := cmd.Requirements(factory, flagContext)
    88  				Expect(err).To(HaveOccurred())
    89  				Expect(ui.Outputs()).To(ContainSubstrings(
    90  					[]string{"Incorrect Usage. Requires SPACE and DOMAIN as arguments"},
    91  					[]string{"NAME"},
    92  					[]string{"USAGE"},
    93  				))
    94  			})
    95  		})
    96  
    97  		Context("when provided exactly two args", func() {
    98  			BeforeEach(func() {
    99  				err := flagContext.Parse("space-name", "domain-name")
   100  				Expect(err).NotTo(HaveOccurred())
   101  			})
   102  
   103  			It("returns a SpaceRequirement", func() {
   104  				actualRequirements, err := cmd.Requirements(factory, flagContext)
   105  				Expect(err).NotTo(HaveOccurred())
   106  				Expect(factory.NewSpaceRequirementCallCount()).To(Equal(1))
   107  				Expect(factory.NewSpaceRequirementArgsForCall(0)).To(Equal("space-name"))
   108  
   109  				Expect(actualRequirements).To(ContainElement(spaceRequirement))
   110  			})
   111  
   112  			It("returns a DomainRequirement", func() {
   113  				actualRequirements, err := cmd.Requirements(factory, flagContext)
   114  				Expect(err).NotTo(HaveOccurred())
   115  				Expect(factory.NewDomainRequirementCallCount()).To(Equal(1))
   116  				Expect(factory.NewDomainRequirementArgsForCall(0)).To(Equal("domain-name"))
   117  
   118  				Expect(actualRequirements).To(ContainElement(domainRequirement))
   119  			})
   120  		})
   121  
   122  		Context("when the --path option is given", func() {
   123  			BeforeEach(func() {
   124  				err := flagContext.Parse("space-name", "domain-name", "--path", "path")
   125  				Expect(err).NotTo(HaveOccurred())
   126  			})
   127  
   128  			It("returns a MinAPIVersionRequirement", func() {
   129  				expectedVersion, err := semver.Make("2.36.0")
   130  				Expect(err).NotTo(HaveOccurred())
   131  
   132  				actualRequirements, err := cmd.Requirements(factory, flagContext)
   133  				Expect(err).NotTo(HaveOccurred())
   134  
   135  				Expect(factory.NewMinAPIVersionRequirementCallCount()).To(Equal(1))
   136  				feature, requiredVersion := factory.NewMinAPIVersionRequirementArgsForCall(0)
   137  				Expect(feature).To(Equal("Option '--path'"))
   138  				Expect(requiredVersion).To(Equal(expectedVersion))
   139  				Expect(actualRequirements).To(ContainElement(minAPIVersionRequirement))
   140  			})
   141  		})
   142  
   143  		Context("when the --port option is given", func() {
   144  			BeforeEach(func() {
   145  				err := flagContext.Parse("space-name", "domain-name", "--port", "9090")
   146  				Expect(err).NotTo(HaveOccurred())
   147  			})
   148  
   149  			It("returns a MinAPIVersionRequirement", func() {
   150  				expectedVersion, err := semver.Make("2.53.0")
   151  				Expect(err).NotTo(HaveOccurred())
   152  
   153  				actualRequirements, err := cmd.Requirements(factory, flagContext)
   154  				Expect(err).NotTo(HaveOccurred())
   155  
   156  				Expect(factory.NewMinAPIVersionRequirementCallCount()).To(Equal(1))
   157  				feature, requiredVersion := factory.NewMinAPIVersionRequirementArgsForCall(0)
   158  				Expect(feature).To(Equal("Option '--port'"))
   159  				Expect(requiredVersion).To(Equal(expectedVersion))
   160  				Expect(actualRequirements).To(ContainElement(minAPIVersionRequirement))
   161  			})
   162  		})
   163  
   164  		Context("when the --random-port option is given", func() {
   165  			BeforeEach(func() {
   166  				err := flagContext.Parse("space-name", "domain-name", "--random-port")
   167  				Expect(err).NotTo(HaveOccurred())
   168  			})
   169  
   170  			It("returns a MinAPIVersionRequirement", func() {
   171  				expectedVersion, err := semver.Make("2.53.0")
   172  				Expect(err).NotTo(HaveOccurred())
   173  
   174  				actualRequirements, err := cmd.Requirements(factory, flagContext)
   175  				Expect(err).NotTo(HaveOccurred())
   176  
   177  				Expect(factory.NewMinAPIVersionRequirementCallCount()).To(Equal(1))
   178  				feature, requiredVersion := factory.NewMinAPIVersionRequirementArgsForCall(0)
   179  				Expect(feature).To(Equal("Option '--random-port'"))
   180  				Expect(requiredVersion).To(Equal(expectedVersion))
   181  				Expect(actualRequirements).To(ContainElement(minAPIVersionRequirement))
   182  			})
   183  		})
   184  
   185  		Context("when the --path option is not given", func() {
   186  			BeforeEach(func() {
   187  				err := flagContext.Parse("space-name", "domain-name")
   188  				Expect(err).NotTo(HaveOccurred())
   189  			})
   190  
   191  			It("does not return a MinAPIVersionRequirement", func() {
   192  				actualRequirements, err := cmd.Requirements(factory, flagContext)
   193  				Expect(err).NotTo(HaveOccurred())
   194  				Expect(actualRequirements).NotTo(ContainElement(minAPIVersionRequirement))
   195  			})
   196  		})
   197  
   198  		Context("when both --port and --hostname are given", func() {
   199  			BeforeEach(func() {
   200  				err := flagContext.Parse("space-name", "domain-name", "--port", "9090", "--hostname", "host")
   201  				Expect(err).NotTo(HaveOccurred())
   202  			})
   203  
   204  			It("fails with error", func() {
   205  				_, err := cmd.Requirements(factory, flagContext)
   206  				Expect(err).To(HaveOccurred())
   207  				Expect(ui.Outputs()).To(ContainSubstrings(
   208  					[]string{"FAILED"},
   209  					[]string{"Cannot specify port together with hostname and/or path."},
   210  				))
   211  			})
   212  		})
   213  
   214  		Context("when both --port and --path are given", func() {
   215  			BeforeEach(func() {
   216  				err := flagContext.Parse("space-name", "domain-name", "--port", "9090", "--path", "path")
   217  				Expect(err).NotTo(HaveOccurred())
   218  			})
   219  
   220  			It("fails with error", func() {
   221  				_, err := cmd.Requirements(factory, flagContext)
   222  				Expect(err).To(HaveOccurred())
   223  				Expect(ui.Outputs()).To(ContainSubstrings(
   224  					[]string{"FAILED"},
   225  					[]string{"Cannot specify port together with hostname and/or path."},
   226  				))
   227  			})
   228  		})
   229  
   230  		Context("when both --port and --random-port are given", func() {
   231  			BeforeEach(func() {
   232  				err := flagContext.Parse("space-name", "domain-name", "--port", "9090", "--random-port")
   233  				Expect(err).NotTo(HaveOccurred())
   234  			})
   235  
   236  			It("fails with error", func() {
   237  				_, err := cmd.Requirements(factory, flagContext)
   238  				Expect(err).To(HaveOccurred())
   239  				Expect(ui.Outputs()).To(ContainSubstrings(
   240  					[]string{"FAILED"},
   241  					[]string{"Cannot specify random-port together with port, hostname and/or path."},
   242  				))
   243  			})
   244  		})
   245  
   246  		Context("when both --random-port and --hostname are given", func() {
   247  			BeforeEach(func() {
   248  				err := flagContext.Parse("space-name", "domain-name", "--hostname", "host", "--random-port")
   249  				Expect(err).NotTo(HaveOccurred())
   250  			})
   251  
   252  			It("fails with error", func() {
   253  				_, err := cmd.Requirements(factory, flagContext)
   254  				Expect(err).To(HaveOccurred())
   255  				Expect(ui.Outputs()).To(ContainSubstrings(
   256  					[]string{"FAILED"},
   257  					[]string{"Cannot specify random-port together with port, hostname and/or path."},
   258  				))
   259  			})
   260  		})
   261  
   262  		Context("when --random-port and --path are given", func() {
   263  			BeforeEach(func() {
   264  				err := flagContext.Parse("space-name", "domain-name", "--path", "path", "--random-port")
   265  				Expect(err).NotTo(HaveOccurred())
   266  			})
   267  
   268  			It("fails with error", func() {
   269  				_, err := cmd.Requirements(factory, flagContext)
   270  				Expect(err).To(HaveOccurred())
   271  				Expect(ui.Outputs()).To(ContainSubstrings(
   272  					[]string{"FAILED"},
   273  					[]string{"Cannot specify random-port together with port, hostname and/or path."},
   274  				))
   275  			})
   276  		})
   277  	})
   278  
   279  	Describe("Execute", func() {
   280  		var err error
   281  
   282  		BeforeEach(func() {
   283  			err := flagContext.Parse("space-name", "domain-name")
   284  			Expect(err).NotTo(HaveOccurred())
   285  			cmd.Requirements(factory, flagContext)
   286  		})
   287  
   288  		JustBeforeEach(func() {
   289  			err = cmd.Execute(flagContext)
   290  		})
   291  
   292  		It("attempts to create a route in the space", func() {
   293  			Expect(err).NotTo(HaveOccurred())
   294  
   295  			Expect(routeRepo.CreateInSpaceCallCount()).To(Equal(1))
   296  			hostname, path, domain, space, port, randomPort := routeRepo.CreateInSpaceArgsForCall(0)
   297  			Expect(hostname).To(Equal(""))
   298  			Expect(path).To(Equal(""))
   299  			Expect(domain).To(Equal("domain-guid"))
   300  			Expect(space).To(Equal("space-guid"))
   301  			Expect(port).To(Equal(0))
   302  			Expect(randomPort).To(BeFalse())
   303  		})
   304  
   305  		Context("when the --path option is given", func() {
   306  			BeforeEach(func() {
   307  				err := flagContext.Parse("space-name", "domain-name", "--path", "some-path")
   308  				Expect(err).NotTo(HaveOccurred())
   309  			})
   310  
   311  			It("tries to create a route with the path", func() {
   312  				Expect(err).NotTo(HaveOccurred())
   313  
   314  				Expect(routeRepo.CreateInSpaceCallCount()).To(Equal(1))
   315  				_, path, _, _, _, _ := routeRepo.CreateInSpaceArgsForCall(0)
   316  				Expect(path).To(Equal("some-path"))
   317  			})
   318  		})
   319  
   320  		Context("when the --random-port option is given", func() {
   321  			BeforeEach(func() {
   322  				err := flagContext.Parse("space-name", "domain-name", "--random-port")
   323  				Expect(err).NotTo(HaveOccurred())
   324  			})
   325  
   326  			It("tries to create a route with a random port", func() {
   327  				Expect(err).NotTo(HaveOccurred())
   328  
   329  				Expect(routeRepo.CreateInSpaceCallCount()).To(Equal(1))
   330  				_, _, _, _, _, randomPort := routeRepo.CreateInSpaceArgsForCall(0)
   331  				Expect(randomPort).To(BeTrue())
   332  			})
   333  		})
   334  
   335  		Context("when the --port option is given", func() {
   336  			BeforeEach(func() {
   337  				err := flagContext.Parse("space-name", "domain-name", "--port", "9090")
   338  				Expect(err).NotTo(HaveOccurred())
   339  			})
   340  
   341  			It("tries to create a route with the port", func() {
   342  				Expect(err).NotTo(HaveOccurred())
   343  
   344  				Expect(routeRepo.CreateInSpaceCallCount()).To(Equal(1))
   345  				_, _, _, _, port, _ := routeRepo.CreateInSpaceArgsForCall(0)
   346  				Expect(port).To(Equal(9090))
   347  			})
   348  		})
   349  
   350  		Context("when the --hostname option is given", func() {
   351  			BeforeEach(func() {
   352  				err := flagContext.Parse("space-name", "domain-name", "--hostname", "host")
   353  				Expect(err).NotTo(HaveOccurred())
   354  			})
   355  
   356  			It("tries to create a route with the hostname", func() {
   357  				Expect(err).NotTo(HaveOccurred())
   358  
   359  				Expect(routeRepo.CreateInSpaceCallCount()).To(Equal(1))
   360  				host, _, _, _, _, _ := routeRepo.CreateInSpaceArgsForCall(0)
   361  				Expect(host).To(Equal("host"))
   362  			})
   363  		})
   364  
   365  		Context("when creating the route fails", func() {
   366  			BeforeEach(func() {
   367  				routeRepo.CreateInSpaceReturns(models.Route{}, errors.New("create-error"))
   368  
   369  				err := flagContext.Parse("space-name", "domain-name", "--port", "9090", "--hostname", "hostname", "--path", "/path")
   370  				Expect(err).NotTo(HaveOccurred())
   371  			})
   372  
   373  			It("attempts to find the route", func() {
   374  				Expect(err).To(HaveOccurred())
   375  				Expect(routeRepo.FindCallCount()).To(Equal(1))
   376  
   377  				host, domain, path, port := routeRepo.FindArgsForCall(0)
   378  				Expect(host).To(Equal("hostname"))
   379  				Expect(domain.Name).To(Equal("domain-name"))
   380  				Expect(path).To(Equal("/path"))
   381  				Expect(port).To(Equal(9090))
   382  			})
   383  
   384  			Context("when finding the route fails", func() {
   385  				BeforeEach(func() {
   386  					routeRepo.FindReturns(models.Route{}, errors.New("find-error"))
   387  				})
   388  
   389  				It("fails with the original error", func() {
   390  					Expect(err).To(HaveOccurred())
   391  					Expect(err.Error()).To(Equal("create-error"))
   392  				})
   393  			})
   394  
   395  			Context("when a route with the same space guid, but different domain guid is found", func() {
   396  				It("fails with the original error", func() {
   397  					Expect(err).To(HaveOccurred())
   398  					Expect(err.Error()).To(Equal("create-error"))
   399  				})
   400  			})
   401  
   402  			Context("when a route with the same domain guid, but different space guid is found", func() {
   403  				It("fails with the original error", func() {
   404  					Expect(err).To(HaveOccurred())
   405  					Expect(err.Error()).To(Equal("create-error"))
   406  				})
   407  			})
   408  
   409  			Context("when a route with the same domain and space guid is found", func() {
   410  				BeforeEach(func() {
   411  					routeRepo.FindReturns(models.Route{
   412  						Domain: models.DomainFields{
   413  							GUID: "domain-guid",
   414  							Name: "domain-name",
   415  						},
   416  						Space: models.SpaceFields{
   417  							GUID: "space-guid",
   418  						},
   419  					}, nil)
   420  				})
   421  
   422  				It("prints a message", func() {
   423  					Expect(err).NotTo(HaveOccurred())
   424  					Expect(ui.Outputs()).To(ContainSubstrings(
   425  						[]string{"OK"},
   426  						[]string{"Route domain-name already exists"},
   427  					))
   428  				})
   429  			})
   430  		})
   431  	})
   432  
   433  	Describe("CreateRoute", func() {
   434  		var domainFields models.DomainFields
   435  		var spaceFields models.SpaceFields
   436  		var rc route.Creator
   437  
   438  		BeforeEach(func() {
   439  			domainFields = models.DomainFields{
   440  				GUID: "domain-guid",
   441  				Name: "domain-name",
   442  			}
   443  			spaceFields = models.SpaceFields{
   444  				GUID: "space-guid",
   445  				Name: "space-name",
   446  			}
   447  
   448  			var ok bool
   449  			rc, ok = cmd.(route.Creator)
   450  			Expect(ok).To(BeTrue())
   451  		})
   452  
   453  		It("attempts to create a route in the space", func() {
   454  			rc.CreateRoute("hostname", "path", 9090, true, domainFields, spaceFields)
   455  
   456  			Expect(routeRepo.CreateInSpaceCallCount()).To(Equal(1))
   457  			hostname, path, domain, space, port, randomPort := routeRepo.CreateInSpaceArgsForCall(0)
   458  			Expect(hostname).To(Equal("hostname"))
   459  			Expect(path).To(Equal("path"))
   460  			Expect(domain).To(Equal(domainFields.GUID))
   461  			Expect(space).To(Equal(spaceFields.GUID))
   462  			Expect(port).To(Equal(9090))
   463  			Expect(randomPort).To(BeTrue())
   464  		})
   465  
   466  		Context("when creating the route fails", func() {
   467  			BeforeEach(func() {
   468  				routeRepo.CreateInSpaceReturns(models.Route{}, errors.New("create-error"))
   469  			})
   470  
   471  			It("attempts to find the route", func() {
   472  				rc.CreateRoute("hostname", "path", 0, false, domainFields, spaceFields)
   473  				Expect(routeRepo.FindCallCount()).To(Equal(1))
   474  			})
   475  
   476  			Context("when finding the route fails", func() {
   477  				BeforeEach(func() {
   478  					routeRepo.FindReturns(models.Route{}, errors.New("find-error"))
   479  				})
   480  
   481  				It("returns the original error", func() {
   482  					_, err := rc.CreateRoute("hostname", "path", 0, false, domainFields, spaceFields)
   483  					Expect(err).To(HaveOccurred())
   484  					Expect(err.Error()).To(Equal("create-error"))
   485  				})
   486  			})
   487  
   488  			Context("when a route with the same space guid, but different domain guid is found", func() {
   489  				It("returns the original error", func() {
   490  					_, err := rc.CreateRoute("hostname", "path", 0, false, domainFields, spaceFields)
   491  					Expect(err).To(HaveOccurred())
   492  					Expect(err.Error()).To(Equal("create-error"))
   493  				})
   494  			})
   495  
   496  			Context("when a route with the same domain guid, but different space guid is found", func() {
   497  				It("returns the original error", func() {
   498  					_, err := rc.CreateRoute("hostname", "path", 0, false, domainFields, spaceFields)
   499  					Expect(err).To(HaveOccurred())
   500  					Expect(err.Error()).To(Equal("create-error"))
   501  				})
   502  			})
   503  
   504  			Context("when a route with the same domain and space guid is found", func() {
   505  				BeforeEach(func() {
   506  					routeRepo.FindReturns(models.Route{
   507  						Host: "hostname",
   508  						Path: "path",
   509  						Domain: models.DomainFields{
   510  							GUID: "domain-guid",
   511  							Name: "domain-name",
   512  						},
   513  						Space: models.SpaceFields{
   514  							GUID: "space-guid",
   515  						},
   516  					}, nil)
   517  				})
   518  
   519  				It("prints a message that it already exists", func() {
   520  					rc.CreateRoute("hostname", "path", 0, false, domainFields, spaceFields)
   521  					Expect(ui.Outputs()).To(ContainSubstrings(
   522  						[]string{"OK"},
   523  						[]string{"Route hostname.domain-name/path already exists"}))
   524  				})
   525  			})
   526  		})
   527  
   528  		Context("when creating the route succeeds", func() {
   529  			var route models.Route
   530  
   531  			JustBeforeEach(func() {
   532  				routeRepo.CreateInSpaceReturns(route, nil)
   533  			})
   534  
   535  			It("prints a success message", func() {
   536  				rc.CreateRoute("hostname", "path", 0, false, domainFields, spaceFields)
   537  				Expect(ui.Outputs()).To(ContainSubstrings([]string{"OK"}))
   538  			})
   539  
   540  			Context("when --random-port is specified", func() {
   541  				BeforeEach(func() {
   542  					route = models.Route{
   543  						Host:   "some-host",
   544  						Domain: domainFields,
   545  						Port:   9090,
   546  					}
   547  				})
   548  
   549  				It("print a success message with created route", func() {
   550  					rc.CreateRoute("hostname", "path", 0, true, domainFields, spaceFields)
   551  					Expect(ui.Outputs()).To(ContainSubstrings(
   552  						[]string{"OK"},
   553  						[]string{"Route domain-name:9090 has been created"},
   554  					))
   555  				})
   556  			})
   557  		})
   558  	})
   559  })