github.com/mook-as/cf-cli@v7.0.0-beta.28.0.20200120190804-b91c115fae48+incompatible/cf/commands/quota/update_quota_test.go (about)

     1  package quota_test
     2  
     3  import (
     4  	"code.cloudfoundry.org/cli/cf/api/quotas/quotasfakes"
     5  	"code.cloudfoundry.org/cli/cf/api/resources"
     6  	"code.cloudfoundry.org/cli/cf/commandregistry"
     7  	cmdsQuota "code.cloudfoundry.org/cli/cf/commands/quota"
     8  	"code.cloudfoundry.org/cli/cf/configuration/coreconfig"
     9  	"code.cloudfoundry.org/cli/cf/errors"
    10  	testcmd "code.cloudfoundry.org/cli/cf/util/testhelpers/commands"
    11  	testconfig "code.cloudfoundry.org/cli/cf/util/testhelpers/configuration"
    12  	. "code.cloudfoundry.org/cli/cf/util/testhelpers/matchers"
    13  	testterm "code.cloudfoundry.org/cli/cf/util/testhelpers/terminal"
    14  
    15  	"encoding/json"
    16  
    17  	"code.cloudfoundry.org/cli/cf/flags"
    18  	"code.cloudfoundry.org/cli/cf/models"
    19  	"code.cloudfoundry.org/cli/cf/requirements"
    20  	"code.cloudfoundry.org/cli/cf/requirements/requirementsfakes"
    21  	. "github.com/onsi/ginkgo"
    22  	. "github.com/onsi/gomega"
    23  )
    24  
    25  var _ = Describe("app Command", func() {
    26  	var (
    27  		ui                  *testterm.FakeUI
    28  		requirementsFactory *requirementsfakes.FakeFactory
    29  		quotaRepo           *quotasfakes.FakeQuotaRepository
    30  		quota               models.QuotaFields
    31  		configRepo          coreconfig.Repository
    32  		deps                commandregistry.Dependency
    33  	)
    34  
    35  	updateCommandDependency := func(pluginCall bool) {
    36  		deps.UI = ui
    37  		deps.Config = configRepo
    38  		deps.RepoLocator = deps.RepoLocator.SetQuotaRepository(quotaRepo)
    39  		commandregistry.Commands.SetCommand(commandregistry.Commands.FindCommand("update-quota").SetDependency(deps, pluginCall))
    40  	}
    41  
    42  	BeforeEach(func() {
    43  		ui = &testterm.FakeUI{}
    44  		configRepo = testconfig.NewRepositoryWithDefaults()
    45  		requirementsFactory = new(requirementsfakes.FakeFactory)
    46  		requirementsFactory.NewLoginRequirementReturns(requirements.Passing{})
    47  		quotaRepo = new(quotasfakes.FakeQuotaRepository)
    48  	})
    49  
    50  	runCommand := func(args ...string) bool {
    51  		return testcmd.RunCLICommand("update-quota", args, requirementsFactory, updateCommandDependency, false, ui)
    52  	}
    53  
    54  	Describe("Help text", func() {
    55  		var usage string
    56  
    57  		BeforeEach(func() {
    58  			uq := &cmdsQuota.UpdateQuota{}
    59  			up := commandregistry.CLICommandUsagePresenter(uq)
    60  			usage = up.Usage()
    61  		})
    62  
    63  		It("has an instance memory flag", func() {
    64  			Expect(usage).To(MatchRegexp(`-i\s+Maximum amount of memory an application instance can have \(e.g. 1024M, 1G, 10G\)`))
    65  
    66  			Expect(usage).To(MatchRegexp(`cf update-quota.*\[-i INSTANCE_MEMORY\]`))
    67  		})
    68  
    69  		It("has a total memory flag", func() {
    70  			Expect(usage).To(MatchRegexp(`-m\s+Total amount of memory \(e.g. 1024M, 1G, 10G\)`))
    71  
    72  			Expect(usage).To(MatchRegexp(`cf update-quota.*\[-m TOTAL_MEMORY\]`))
    73  		})
    74  
    75  		It("has a new name flag", func() {
    76  			Expect(usage).To(MatchRegexp(`-n\s+New name`))
    77  
    78  			Expect(usage).To(MatchRegexp(`cf update-quota.*\[-n NEW_NAME\]`))
    79  		})
    80  
    81  		It("has a routes flag", func() {
    82  			Expect(usage).To(MatchRegexp(`-r\s+Total number of routes`))
    83  
    84  			Expect(usage).To(MatchRegexp(`cf update-quota.*\[-r ROUTES\]`))
    85  		})
    86  
    87  		It("has a service instances flag", func() {
    88  			Expect(usage).To(MatchRegexp(`-s\s+Total number of service instances`))
    89  
    90  			Expect(usage).To(MatchRegexp(`cf update-quota.*\[-s SERVICE_INSTANCES\]`))
    91  		})
    92  
    93  		It("has an app instances flag", func() {
    94  			Expect(usage).To(MatchRegexp(`-a\s+Total number of application instances. -1 represents an unlimited amount.`))
    95  
    96  			Expect(usage).To(MatchRegexp(`cf update-quota.*\[-a APP_INSTANCES\]`))
    97  		})
    98  
    99  		It("has an allow-paid-service-plans flag", func() {
   100  			Expect(usage).To(MatchRegexp(`--allow-paid-service-plans\s+Can provision instances of paid service plans`))
   101  
   102  			Expect(usage).To(MatchRegexp(`cf update-quota.*\[--allow-paid-service-plans`))
   103  		})
   104  
   105  		It("has a disallow-paid-service-plans flag", func() {
   106  			Expect(usage).To(MatchRegexp(`--disallow-paid-service-plans\s+Cannot provision instances of paid service plans`))
   107  
   108  			Expect(usage).To(MatchRegexp(`cf update-quota.*\--disallow-paid-service-plans\]`))
   109  		})
   110  
   111  		It("has a --reserved-route-ports flag", func() {
   112  			Expect(usage).To(MatchRegexp(`--reserved-route-ports\s+Maximum number of routes that may be created with reserved ports`))
   113  
   114  			Expect(usage).To(MatchRegexp(`cf update-quota.*\--reserved-route-ports RESERVED_ROUTE_PORTS\]`))
   115  		})
   116  	})
   117  
   118  	Context("when the user is not logged in", func() {
   119  		BeforeEach(func() {
   120  			requirementsFactory.NewLoginRequirementReturns(requirements.Failing{Message: "not logged in"})
   121  		})
   122  
   123  		It("fails requirements", func() {
   124  			Expect(runCommand("my-quota", "-m", "50G")).To(BeFalse())
   125  		})
   126  	})
   127  
   128  	Context("when the user is logged in", func() {
   129  		BeforeEach(func() {
   130  			quota = models.QuotaFields{
   131  				GUID:             "quota-guid",
   132  				Name:             "quota-name",
   133  				MemoryLimit:      1024,
   134  				RoutesLimit:      111,
   135  				ServicesLimit:    222,
   136  				AppInstanceLimit: 333,
   137  			}
   138  		})
   139  
   140  		JustBeforeEach(func() {
   141  			quotaRepo.FindByNameReturns(quota, nil)
   142  		})
   143  
   144  		Context("when the -i flag is provided", func() {
   145  			It("updates the instance memory limit", func() {
   146  				runCommand("-i", "15G", "quota-name")
   147  				Expect(quotaRepo.UpdateArgsForCall(0).Name).To(Equal("quota-name"))
   148  				Expect(quotaRepo.UpdateArgsForCall(0).InstanceMemoryLimit).To(Equal(int64(15360)))
   149  			})
   150  
   151  			It("totally accepts -1 as a value because it means unlimited", func() {
   152  				runCommand("-i", "-1", "quota-name")
   153  				Expect(quotaRepo.UpdateArgsForCall(0).Name).To(Equal("quota-name"))
   154  				Expect(quotaRepo.UpdateArgsForCall(0).InstanceMemoryLimit).To(Equal(int64(-1)))
   155  			})
   156  
   157  			It("fails with usage when the value cannot be parsed", func() {
   158  				runCommand("-m", "blasé", "le-tired")
   159  				Expect(ui.Outputs()).To(ContainSubstrings(
   160  					[]string{"Incorrect Usage"},
   161  				))
   162  			})
   163  		})
   164  
   165  		Context("when the -a flag is provided", func() {
   166  			It("updated the total number of application instances limit", func() {
   167  				runCommand("-a", "2", "quota-name")
   168  				Expect(quotaRepo.UpdateCallCount()).To(Equal(1))
   169  				Expect(quotaRepo.UpdateArgsForCall(0).AppInstanceLimit).To(Equal(2))
   170  			})
   171  
   172  			It("totally accepts -1 as a value because it means unlimited", func() {
   173  				runCommand("-a", "-1", "quota-name")
   174  				Expect(quotaRepo.UpdateCallCount()).To(Equal(1))
   175  				Expect(quotaRepo.UpdateArgsForCall(0).AppInstanceLimit).To(Equal(resources.UnlimitedAppInstances))
   176  			})
   177  
   178  			It("does not override the value if a different field is updated", func() {
   179  				runCommand("-s", "5", "quota-name")
   180  				Expect(quotaRepo.UpdateCallCount()).To(Equal(1))
   181  				Expect(quotaRepo.UpdateArgsForCall(0).AppInstanceLimit).To(Equal(333))
   182  			})
   183  		})
   184  
   185  		Context("when the -m flag is provided", func() {
   186  			It("updates the memory limit", func() {
   187  				runCommand("-m", "15G", "quota-name")
   188  				Expect(quotaRepo.UpdateArgsForCall(0).Name).To(Equal("quota-name"))
   189  				Expect(quotaRepo.UpdateArgsForCall(0).MemoryLimit).To(Equal(int64(15360)))
   190  			})
   191  
   192  			It("fails with usage when the value cannot be parsed", func() {
   193  				runCommand("-m", "blasé", "le-tired")
   194  				Expect(ui.Outputs()).To(ContainSubstrings(
   195  					[]string{"Incorrect Usage"},
   196  				))
   197  			})
   198  		})
   199  
   200  		Context("when the -n flag is provided", func() {
   201  			It("updates the quota name", func() {
   202  				runCommand("-n", "quota-new-name", "quota-name")
   203  
   204  				Expect(quotaRepo.UpdateArgsForCall(0).Name).To(Equal("quota-new-name"))
   205  
   206  				Expect(ui.Outputs()).To(ContainSubstrings(
   207  					[]string{"Updating quota", "quota-name", "as", "my-user"},
   208  					[]string{"OK"},
   209  				))
   210  			})
   211  		})
   212  
   213  		Context("when the --reserved-route-ports flag is provided", func() {
   214  			It("updates the route port limit", func() {
   215  				runCommand("--reserved-route-ports", "5", "quota-name")
   216  
   217  				Expect(quotaRepo.UpdateCallCount()).To(Equal(1))
   218  				Expect(quotaRepo.UpdateArgsForCall(0).ReservedRoutePorts).To(Equal(json.Number("5")))
   219  			})
   220  
   221  			It("can update the route port limit to be -1, infinity", func() {
   222  				runCommand("--reserved-route-ports", "-1", "quota-name")
   223  
   224  				Expect(quotaRepo.UpdateCallCount()).To(Equal(1))
   225  				Expect(quotaRepo.UpdateArgsForCall(0).ReservedRoutePorts).To(Equal(json.Number("-1")))
   226  			})
   227  		})
   228  
   229  		It("updates the total allowed services", func() {
   230  			runCommand("-s", "9000", "quota-name")
   231  			Expect(quotaRepo.UpdateArgsForCall(0).ServicesLimit).To(Equal(9000))
   232  		})
   233  
   234  		It("updates the total allowed routes", func() {
   235  			runCommand("-r", "9001", "quota-name")
   236  			Expect(quotaRepo.UpdateArgsForCall(0).RoutesLimit).To(Equal(9001))
   237  		})
   238  
   239  		Context("update paid service plans", func() {
   240  			BeforeEach(func() {
   241  				quota.NonBasicServicesAllowed = false
   242  			})
   243  
   244  			It("changes to paid service plan when --allow flag is provided", func() {
   245  				runCommand("--allow-paid-service-plans", "quota-name")
   246  				Expect(quotaRepo.UpdateArgsForCall(0).NonBasicServicesAllowed).To(BeTrue())
   247  			})
   248  
   249  			It("shows an error when both --allow and --disallow flags are provided", func() {
   250  				runCommand("--allow-paid-service-plans", "--disallow-paid-service-plans", "quota-name")
   251  
   252  				Expect(ui.Outputs()).To(ContainSubstrings(
   253  					[]string{"FAILED"},
   254  					[]string{"Both flags are not permitted"},
   255  				))
   256  			})
   257  
   258  			Context("when paid services are allowed", func() {
   259  				BeforeEach(func() {
   260  					quota.NonBasicServicesAllowed = true
   261  				})
   262  				It("changes to non-paid service plan when --disallow flag is provided", func() {
   263  					quotaRepo.FindByNameReturns(quota, nil) // updating an existing quota
   264  
   265  					runCommand("--disallow-paid-service-plans", "quota-name")
   266  					Expect(quotaRepo.UpdateArgsForCall(0).NonBasicServicesAllowed).To(BeFalse())
   267  				})
   268  			})
   269  		})
   270  
   271  		It("shows an error when updating fails", func() {
   272  			quotaRepo.UpdateReturns(errors.New("I accidentally a quota"))
   273  			runCommand("-m", "1M", "dead-serious")
   274  			Expect(ui.Outputs()).To(ContainSubstrings([]string{"FAILED"}))
   275  		})
   276  
   277  		It("shows a message explaining the update", func() {
   278  			quota.Name = "i-love-ui"
   279  			quotaRepo.FindByNameReturns(quota, nil)
   280  
   281  			runCommand("-m", "50G", "i-love-ui")
   282  			Expect(ui.Outputs()).To(ContainSubstrings(
   283  				[]string{"Updating quota", "i-love-ui", "as", "my-user"},
   284  				[]string{"OK"},
   285  			))
   286  		})
   287  
   288  		It("shows the user an error when finding the quota fails", func() {
   289  			quotaRepo.FindByNameReturns(models.QuotaFields{}, errors.New("i can't believe it's not quotas!"))
   290  
   291  			runCommand("-m", "50Somethings", "what-could-possibly-go-wrong?")
   292  			Expect(ui.Outputs()).To(ContainSubstrings([]string{"FAILED"}))
   293  		})
   294  	})
   295  
   296  	Describe("Requirements", func() {
   297  		var (
   298  			requirementsFactory *requirementsfakes.FakeFactory
   299  
   300  			ui   *testterm.FakeUI
   301  			cmd  commandregistry.Command
   302  			deps commandregistry.Dependency
   303  
   304  			quotaRepo   *quotasfakes.FakeQuotaRepository
   305  			flagContext flags.FlagContext
   306  
   307  			loginRequirement requirements.Requirement
   308  		)
   309  
   310  		BeforeEach(func() {
   311  			ui = &testterm.FakeUI{}
   312  
   313  			configRepo = testconfig.NewRepositoryWithDefaults()
   314  			quotaRepo = new(quotasfakes.FakeQuotaRepository)
   315  			repoLocator := deps.RepoLocator.SetQuotaRepository(quotaRepo)
   316  
   317  			deps = commandregistry.Dependency{
   318  				UI:          ui,
   319  				Config:      configRepo,
   320  				RepoLocator: repoLocator,
   321  			}
   322  
   323  			requirementsFactory = new(requirementsfakes.FakeFactory)
   324  
   325  			cmd = &cmdsQuota.UpdateQuota{}
   326  			cmd.SetDependency(deps, false)
   327  
   328  			flagContext = flags.NewFlagContext(cmd.MetaData().Flags)
   329  
   330  			loginRequirement = &passingRequirement{Name: "login-requirement"}
   331  			requirementsFactory.NewLoginRequirementReturns(loginRequirement)
   332  		})
   333  
   334  		Context("when not provided exactly one arg", func() {
   335  			BeforeEach(func() {
   336  				flagContext.Parse("quota", "extra-arg")
   337  			})
   338  
   339  			It("fails with usage", func() {
   340  				_, err := cmd.Requirements(requirementsFactory, flagContext)
   341  				Expect(err).To(HaveOccurred())
   342  				Expect(ui.Outputs()).To(ContainSubstrings(
   343  					[]string{"FAILED"},
   344  					[]string{"Incorrect Usage. Requires an argument"},
   345  				))
   346  			})
   347  		})
   348  
   349  		Context("when provided exactly one arg", func() {
   350  			BeforeEach(func() {
   351  				flagContext.Parse("quota")
   352  			})
   353  
   354  			It("returns a LoginRequirement", func() {
   355  				actualRequirements, err := cmd.Requirements(requirementsFactory, flagContext)
   356  				Expect(err).NotTo(HaveOccurred())
   357  				Expect(requirementsFactory.NewLoginRequirementCallCount()).To(Equal(1))
   358  				Expect(actualRequirements).To(ContainElement(loginRequirement))
   359  			})
   360  		})
   361  	})
   362  })