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 })