github.com/swisscom/cloudfoundry-cli@v7.1.0+incompatible/cf/commands/quota/create_quota_test.go (about)

     1  package quota_test
     2  
     3  import (
     4  	"code.cloudfoundry.org/cli/cf/commandregistry"
     5  	"code.cloudfoundry.org/cli/cf/configuration/coreconfig"
     6  	"code.cloudfoundry.org/cli/cf/flags"
     7  	. "code.cloudfoundry.org/cli/cf/util/testhelpers/matchers"
     8  	. "github.com/onsi/ginkgo"
     9  	. "github.com/onsi/gomega"
    10  
    11  	"encoding/json"
    12  
    13  	"code.cloudfoundry.org/cli/cf/api/quotas/quotasfakes"
    14  	"code.cloudfoundry.org/cli/cf/api/resources"
    15  	"code.cloudfoundry.org/cli/cf/commands/quota"
    16  	"code.cloudfoundry.org/cli/cf/errors"
    17  	"code.cloudfoundry.org/cli/cf/requirements"
    18  	"code.cloudfoundry.org/cli/cf/requirements/requirementsfakes"
    19  	testcmd "code.cloudfoundry.org/cli/cf/util/testhelpers/commands"
    20  	testconfig "code.cloudfoundry.org/cli/cf/util/testhelpers/configuration"
    21  	testterm "code.cloudfoundry.org/cli/cf/util/testhelpers/terminal"
    22  )
    23  
    24  var _ = Describe("create-quota command", func() {
    25  	var (
    26  		ui                  *testterm.FakeUI
    27  		quotaRepo           *quotasfakes.FakeQuotaRepository
    28  		requirementsFactory *requirementsfakes.FakeFactory
    29  		configRepo          coreconfig.Repository
    30  		deps                commandregistry.Dependency
    31  	)
    32  
    33  	updateCommandDependency := func(pluginCall bool) {
    34  		deps.UI = ui
    35  		deps.Config = configRepo
    36  		deps.RepoLocator = deps.RepoLocator.SetQuotaRepository(quotaRepo)
    37  		commandregistry.Commands.SetCommand(commandregistry.Commands.FindCommand("create-quota").SetDependency(deps, pluginCall))
    38  	}
    39  
    40  	BeforeEach(func() {
    41  		ui = &testterm.FakeUI{}
    42  		configRepo = testconfig.NewRepositoryWithDefaults()
    43  		quotaRepo = new(quotasfakes.FakeQuotaRepository)
    44  		requirementsFactory = new(requirementsfakes.FakeFactory)
    45  	})
    46  
    47  	runCommand := func(args ...string) bool {
    48  		return testcmd.RunCLICommand("create-quota", args, requirementsFactory, updateCommandDependency, false, ui)
    49  	}
    50  
    51  	Describe("Help text", func() {
    52  		var usage string
    53  
    54  		BeforeEach(func() {
    55  			cq := &quota.CreateQuota{}
    56  			up := commandregistry.CLICommandUsagePresenter(cq)
    57  			usage = up.Usage()
    58  		})
    59  
    60  		It("has a reserved route ports flag", func() {
    61  			Expect(usage).To(MatchRegexp(`--reserved-route-ports\s+Maximum number of routes that may be created with reserved ports \(Default: 0\)`))
    62  
    63  			Expect(usage).To(MatchRegexp(`cf create-quota.*\[--reserved-route-ports RESERVED_ROUTE_PORTS\]`))
    64  		})
    65  
    66  		It("has an instance memory flag", func() {
    67  			Expect(usage).To(MatchRegexp(`-i\s+Maximum amount of memory an application instance can have \(e.g. 1024M, 1G, 10G\). -1 represents an unlimited amount.`))
    68  
    69  			Expect(usage).To(MatchRegexp(`cf create-quota.*\[-i INSTANCE_MEMORY\]`))
    70  		})
    71  
    72  		It("has a total memory flag", func() {
    73  			Expect(usage).To(MatchRegexp(`-m\s+Total amount of memory \(e.g. 1024M, 1G, 10G\)`))
    74  
    75  			Expect(usage).To(MatchRegexp(`cf create-quota.*\[-m TOTAL_MEMORY\]`))
    76  		})
    77  
    78  		It("has a routes flag", func() {
    79  			Expect(usage).To(MatchRegexp(`-r\s+Total number of routes`))
    80  
    81  			Expect(usage).To(MatchRegexp(`cf create-quota.*\[-r ROUTES\]`))
    82  		})
    83  
    84  		It("has a service instances flag", func() {
    85  			Expect(usage).To(MatchRegexp(`-s\s+Total number of service instances`))
    86  
    87  			Expect(usage).To(MatchRegexp(`cf create-quota.*\[-s SERVICE_INSTANCES\]`))
    88  		})
    89  
    90  		It("has an app instances flag", func() {
    91  			Expect(usage).To(MatchRegexp(`-a\s+Total number of application instances. -1 represents an unlimited amount. \(Default: unlimited\)`))
    92  
    93  			Expect(usage).To(MatchRegexp(`cf create-quota.*\[-a APP_INSTANCES\]`))
    94  		})
    95  	})
    96  
    97  	Context("when the user is not logged in", func() {
    98  		BeforeEach(func() {
    99  			requirementsFactory.NewLoginRequirementReturns(requirements.Failing{Message: "not logged in"})
   100  		})
   101  
   102  		It("fails requirements", func() {
   103  			Expect(runCommand("my-quota", "-m", "50G")).To(BeFalse())
   104  		})
   105  	})
   106  
   107  	Context("when the user is logged in", func() {
   108  		BeforeEach(func() {
   109  			requirementsFactory.NewLoginRequirementReturns(requirements.Passing{})
   110  			requirementsFactory.NewMinAPIVersionRequirementReturns(requirements.Passing{})
   111  		})
   112  
   113  		It("fails requirements when called without a quota name", func() {
   114  			runCommand()
   115  			Expect(ui.Outputs()).To(ContainSubstrings(
   116  				[]string{"Incorrect Usage", "Requires an argument"},
   117  			))
   118  		})
   119  
   120  		It("creates a quota with a given name", func() {
   121  			runCommand("my-quota")
   122  			Expect(quotaRepo.CreateArgsForCall(0).Name).To(Equal("my-quota"))
   123  			Expect(ui.Outputs()).To(ContainSubstrings(
   124  				[]string{"Creating quota", "my-quota", "my-user", "..."},
   125  				[]string{"OK"},
   126  			))
   127  		})
   128  
   129  		Context("when the -i flag is not provided", func() {
   130  			It("defaults the memory limit to unlimited", func() {
   131  				runCommand("my-quota")
   132  
   133  				Expect(quotaRepo.CreateArgsForCall(0).InstanceMemoryLimit).To(Equal(int64(-1)))
   134  			})
   135  		})
   136  
   137  		Context("when the -m flag is provided", func() {
   138  			It("sets the memory limit", func() {
   139  				runCommand("-m", "50G", "erryday makin fitty jeez")
   140  				Expect(quotaRepo.CreateArgsForCall(0).MemoryLimit).To(Equal(int64(51200)))
   141  			})
   142  
   143  			It("alerts the user when parsing the memory limit fails", func() {
   144  				runCommand("whoops", "12")
   145  
   146  				Expect(ui.Outputs()).To(ContainSubstrings([]string{"FAILED"}))
   147  			})
   148  		})
   149  
   150  		Context("when the -i flag is provided", func() {
   151  			It("sets the memory limit", func() {
   152  				runCommand("-i", "50G", "erryday makin fitty jeez")
   153  				Expect(quotaRepo.CreateArgsForCall(0).InstanceMemoryLimit).To(Equal(int64(51200)))
   154  			})
   155  
   156  			It("alerts the user when parsing the memory limit fails", func() {
   157  				runCommand("-i", "whoops", "wit mah hussle", "12")
   158  
   159  				Expect(ui.Outputs()).To(ContainSubstrings([]string{"FAILED"}))
   160  			})
   161  
   162  			Context("and the provided value is -1", func() {
   163  				It("sets the memory limit", func() {
   164  					runCommand("-i", "-1", "yo")
   165  					Expect(quotaRepo.CreateArgsForCall(0).InstanceMemoryLimit).To(Equal(int64(-1)))
   166  				})
   167  			})
   168  		})
   169  
   170  		Context("when the -a flag is provided", func() {
   171  			It("sets the app limit", func() {
   172  				runCommand("my-quota", "-a", "10")
   173  
   174  				Expect(quotaRepo.CreateArgsForCall(0).AppInstanceLimit).To(Equal(10))
   175  			})
   176  
   177  			It("defaults to unlimited", func() {
   178  				runCommand("my-quota")
   179  
   180  				Expect(quotaRepo.CreateArgsForCall(0).AppInstanceLimit).To(Equal(resources.UnlimitedAppInstances))
   181  			})
   182  		})
   183  
   184  		Context("when the --reserved-route-ports flag is provided", func() {
   185  			It("sets route port limit", func() {
   186  				runCommand("my-quota", "--reserved-route-ports", "5")
   187  
   188  				Expect(quotaRepo.CreateArgsForCall(0).ReservedRoutePorts).To(Equal(json.Number("5")))
   189  			})
   190  
   191  			It("defaults be empty", func() {
   192  				runCommand("my-quota")
   193  
   194  				Expect(quotaRepo.CreateArgsForCall(0).ReservedRoutePorts).To(BeEmpty())
   195  			})
   196  		})
   197  
   198  		It("sets the route limit", func() {
   199  			runCommand("-r", "12", "ecstatic")
   200  
   201  			Expect(quotaRepo.CreateArgsForCall(0).RoutesLimit).To(Equal(12))
   202  		})
   203  
   204  		It("sets the service instance limit", func() {
   205  			runCommand("-s", "42", "black star")
   206  			Expect(quotaRepo.CreateArgsForCall(0).ServicesLimit).To(Equal(42))
   207  		})
   208  
   209  		Context("when requesting to allow paid service plans", func() {
   210  			It("creates the quota with paid service plans allowed", func() {
   211  				runCommand("--allow-paid-service-plans", "my-for-profit-quota")
   212  				Expect(quotaRepo.CreateArgsForCall(0).NonBasicServicesAllowed).To(BeTrue())
   213  			})
   214  
   215  			It("defaults to not allowing paid service plans", func() {
   216  				runCommand("my-pro-bono-quota")
   217  				Expect(quotaRepo.CreateArgsForCall(0).NonBasicServicesAllowed).To(BeFalse())
   218  			})
   219  		})
   220  
   221  		Context("when creating a quota returns an error", func() {
   222  			It("alerts the user when creating the quota fails", func() {
   223  				quotaRepo.CreateReturns(errors.New("WHOOP THERE IT IS"))
   224  				runCommand("my-quota")
   225  
   226  				Expect(ui.Outputs()).To(ContainSubstrings(
   227  					[]string{"Creating quota", "my-quota"},
   228  					[]string{"FAILED"},
   229  				))
   230  			})
   231  
   232  			It("warns the user when quota already exists", func() {
   233  				quotaRepo.CreateReturns(errors.NewHTTPError(400, errors.QuotaDefinitionNameTaken, "Quota Definition is taken: quota-sct"))
   234  				runCommand("Banana")
   235  
   236  				Expect(ui.Outputs()).ToNot(ContainSubstrings(
   237  					[]string{"FAILED"},
   238  				))
   239  				Expect(ui.WarnOutputs).To(ContainSubstrings([]string{"already exists"}))
   240  			})
   241  
   242  		})
   243  	})
   244  
   245  	Describe("Requirements", func() {
   246  		var (
   247  			requirementsFactory *requirementsfakes.FakeFactory
   248  
   249  			ui   *testterm.FakeUI
   250  			cmd  commandregistry.Command
   251  			deps commandregistry.Dependency
   252  
   253  			quotaRepo   *quotasfakes.FakeQuotaRepository
   254  			flagContext flags.FlagContext
   255  
   256  			loginRequirement requirements.Requirement
   257  		)
   258  
   259  		BeforeEach(func() {
   260  			ui = &testterm.FakeUI{}
   261  
   262  			configRepo = testconfig.NewRepositoryWithDefaults()
   263  			quotaRepo = new(quotasfakes.FakeQuotaRepository)
   264  			repoLocator := deps.RepoLocator.SetQuotaRepository(quotaRepo)
   265  
   266  			deps = commandregistry.Dependency{
   267  				UI:          ui,
   268  				Config:      configRepo,
   269  				RepoLocator: repoLocator,
   270  			}
   271  
   272  			requirementsFactory = new(requirementsfakes.FakeFactory)
   273  
   274  			cmd = &quota.CreateQuota{}
   275  			cmd.SetDependency(deps, false)
   276  
   277  			flagContext = flags.NewFlagContext(cmd.MetaData().Flags)
   278  
   279  			loginRequirement = &passingRequirement{Name: "login-requirement"}
   280  			requirementsFactory.NewLoginRequirementReturns(loginRequirement)
   281  		})
   282  
   283  		Context("when not provided exactly one arg", func() {
   284  			BeforeEach(func() {
   285  				flagContext.Parse("quota", "extra-arg")
   286  			})
   287  
   288  			It("fails with usage", func() {
   289  				_, err := cmd.Requirements(requirementsFactory, flagContext)
   290  				Expect(err).To(HaveOccurred())
   291  				Expect(ui.Outputs()).To(ContainSubstrings(
   292  					[]string{"FAILED"},
   293  					[]string{"Incorrect Usage. Requires an argument"},
   294  				))
   295  			})
   296  		})
   297  
   298  		Context("when provided exactly one arg", func() {
   299  			BeforeEach(func() {
   300  				flagContext.Parse("quota")
   301  			})
   302  
   303  			It("returns a LoginRequirement", func() {
   304  				actualRequirements, err := cmd.Requirements(requirementsFactory, flagContext)
   305  				Expect(err).NotTo(HaveOccurred())
   306  				Expect(requirementsFactory.NewLoginRequirementCallCount()).To(Equal(1))
   307  				Expect(actualRequirements).To(ContainElement(loginRequirement))
   308  			})
   309  		})
   310  	})
   311  })
   312  
   313  type passingRequirement struct {
   314  	Name string
   315  }
   316  
   317  func (r passingRequirement) Execute() error {
   318  	return nil
   319  }