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 := "a.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 = "a.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 }