github.com/mook-as/cf-cli@v7.0.0-beta.28.0.20200120190804-b91c115fae48+incompatible/integration/shared/isolated/create_service_command_test.go (about) 1 package isolated 2 3 import ( 4 "io/ioutil" 5 "os" 6 "path/filepath" 7 8 "code.cloudfoundry.org/cli/api/cloudcontroller/ccversion" 9 "code.cloudfoundry.org/cli/integration/helpers" 10 "code.cloudfoundry.org/cli/integration/helpers/fakeservicebroker" 11 . "github.com/onsi/ginkgo" 12 . "github.com/onsi/gomega" 13 . "github.com/onsi/gomega/gbytes" 14 . "github.com/onsi/gomega/gexec" 15 ) 16 17 var _ = Describe("create-service command", func() { 18 Describe("help", func() { 19 When("--help flag is set", func() { 20 It("displays command usage to output", func() { 21 session := helpers.CF("create-service", "--help") 22 Eventually(session).Should(Say("NAME:")) 23 Eventually(session).Should(Say(`\s+create-service - Create a service instance`)) 24 Eventually(session).Should(Say(`USAGE:`)) 25 Eventually(session).Should(Say(`\s+cf create-service SERVICE PLAN SERVICE_INSTANCE \[-b BROKER\] \[-c PARAMETERS_AS_JSON\] \[-t TAGS\]`)) 26 Eventually(session).Should(Say(`\s+Optionally provide service-specific configuration parameters in a valid JSON object in-line:`)) 27 Eventually(session).Should(Say(`\s+cf create-service SERVICE PLAN SERVICE_INSTANCE -c '{\"name\":\"value\",\"name\":\"value\"}'`)) 28 Eventually(session).Should(Say(`\s+Optionally provide a file containing service-specific configuration parameters in a valid JSON object\.`)) 29 Eventually(session).Should(Say(`\s+The path to the parameters file can be an absolute or relative path to a file:`)) 30 Eventually(session).Should(Say(`\s+cf create-service SERVICE PLAN SERVICE_INSTANCE -c PATH_TO_FILE`)) 31 Eventually(session).Should(Say(`\s+Example of valid JSON object:`)) 32 Eventually(session).Should(Say(`\s+{`)) 33 Eventually(session).Should(Say(`\s+\"cluster_nodes\": {`)) 34 Eventually(session).Should(Say(`\s+\"count\": 5,`)) 35 Eventually(session).Should(Say(`\s+\"memory_mb\": 1024`)) 36 Eventually(session).Should(Say(`\s+}`)) 37 Eventually(session).Should(Say(`\s+}`)) 38 Eventually(session).Should(Say(`TIP:`)) 39 Eventually(session).Should(Say(`\s+Use 'cf create-user-provided-service' to make user-provided services available to CF apps`)) 40 Eventually(session).Should(Say(`EXAMPLES:`)) 41 Eventually(session).Should(Say(`\s+Linux/Mac:`)) 42 Eventually(session).Should(Say(`\s+cf create-service db-service silver mydb -c '{\"ram_gb\":4}'`)) 43 Eventually(session).Should(Say(`\s+Windows Command Line:`)) 44 Eventually(session).Should(Say(`\s+cf create-service db-service silver mydb -c \"{\\\"ram_gb\\\":4}\"`)) 45 Eventually(session).Should(Say(`\s+Windows PowerShell:`)) 46 Eventually(session).Should(Say(`\s+cf create-service db-service silver mydb -c '{\\\"ram_gb\\\":4}'`)) 47 Eventually(session).Should(Say(`\s+cf create-service db-service silver mydb -c ~/workspace/tmp/instance_config.json`)) 48 Eventually(session).Should(Say(`\s+cf create-service db-service silver mydb -t \"list, of, tags\"`)) 49 Eventually(session).Should(Say(`ALIAS:`)) 50 Eventually(session).Should(Say(`\s+cs`)) 51 Eventually(session).Should(Say(`OPTIONS:`)) 52 Eventually(session).Should(Say(`\s+-b Create a service instance from a particular broker\. Required when service name is ambiguous`)) 53 Eventually(session).Should(Say(`\s+-c Valid JSON object containing service-specific configuration parameters, provided either in-line or in a file\. For a list of supported configuration parameters, see documentation for the particular service offering\.`)) 54 Eventually(session).Should(Say(`\s+-t User provided tags`)) 55 Eventually(session).Should(Say(`SEE ALSO:`)) 56 Eventually(session).Should(Say(`\s+bind-service, create-user-provided-service, marketplace, services`)) 57 Eventually(session).Should(Exit(0)) 58 }) 59 }) 60 }) 61 62 When("not logged in", func() { 63 BeforeEach(func() { 64 helpers.LogoutCF() 65 }) 66 67 It("displays FAILED, an informative error message, and exits 1", func() { 68 session := helpers.CF("create-service", "service", "plan", "my-service") 69 Eventually(session).Should(Say("FAILED")) 70 Eventually(session.Err).Should(Say("Not logged in. Use 'cf login' or 'cf login --sso' to log in\\.")) 71 Eventually(session).Should(Exit(1)) 72 }) 73 }) 74 75 When("logged in", func() { 76 BeforeEach(func() { 77 helpers.LoginCF() 78 }) 79 80 When("the environment is not setup correctly", func() { 81 It("fails with the appropriate errors", func() { 82 helpers.CheckEnvironmentTargetedCorrectly(true, true, ReadOnlyOrg, "create-service", "service-name", "simple", "new-service") 83 }) 84 }) 85 86 When("the environment is setup correctly", func() { 87 var ( 88 org string 89 space string 90 username string 91 ) 92 93 BeforeEach(func() { 94 org = helpers.NewOrgName() 95 space = helpers.NewSpaceName() 96 97 helpers.SetupCF(org, space) 98 99 username, _ = helpers.GetCredentials() 100 }) 101 102 AfterEach(func() { 103 helpers.QuickDeleteOrg(org) 104 }) 105 106 When("not providing any arguments", func() { 107 It("displays an invalid usage error and the help text, and exits 1", func() { 108 session := helpers.CF("create-service") 109 Eventually(session.Err).Should(Say("Incorrect Usage: the required arguments `SERVICE`, `SERVICE_PLAN` and `SERVICE_INSTANCE` were not provided")) 110 111 // checking partial help text, too long and it's tested earlier 112 Eventually(session).Should(Say("NAME:")) 113 Eventually(session).Should(Say(`\s+create-service - Create a service instance`)) 114 Eventually(session).Should(Exit(1)) 115 }) 116 }) 117 118 When("invalid arguments are passed", func() { 119 When("with an invalid json for -c", func() { 120 It("displays an informative error message, exits 1", func() { 121 session := helpers.CF("create-service", "foo", "bar", "my-service", "-c", "{") 122 Eventually(session.Err).Should(Say("Invalid configuration provided for -c flag. Please provide a valid JSON object or path to a file containing a valid JSON object\\.")) 123 Eventually(session).Should(Exit(1)) 124 }) 125 }) 126 127 When("the provided file contains invalid json", func() { 128 var tempFilePath string 129 130 BeforeEach(func() { 131 tempFilePath = helpers.TempFileWithContent(`{"invalid"}`) 132 }) 133 134 AfterEach(func() { 135 Expect(os.Remove(tempFilePath)).To(Succeed()) 136 }) 137 138 It("displays an informative message and exits 1", func() { 139 session := helpers.CF("create-service", "foo", "bar", "my-service", "-c", tempFilePath) 140 Eventually(session.Err).Should(Say("Invalid configuration provided for -c flag. Please provide a valid JSON object or path to a file containing a valid JSON object\\.")) 141 Eventually(session).Should(Exit(1)) 142 }) 143 }) 144 145 When("the provided file cannot be read", func() { 146 var emptyDir string 147 148 BeforeEach(func() { 149 var err error 150 emptyDir, err = ioutil.TempDir("", "") 151 Expect(err).NotTo(HaveOccurred()) 152 }) 153 154 AfterEach(func() { 155 Expect(os.RemoveAll(emptyDir)).To(Succeed()) 156 }) 157 158 It("displays an informative message and exits 1", func() { 159 session := helpers.CF("create-service", "foo", "bar", "my-service", "-c", filepath.Join(emptyDir, "non-existent-file")) 160 Eventually(session.Err).Should(Say("Invalid configuration provided for -c flag. Please provide a valid JSON object or path to a file containing a valid JSON object\\.")) 161 Eventually(session).Should(Exit(1)) 162 }) 163 }) 164 }) 165 166 When("the service provided is not accessible", func() { 167 It("displays an informative message, exits 1", func() { 168 session := helpers.CF("create-service", "some-service", "some-plan", "my-service") 169 Eventually(session).Should(Say("Creating service instance %s in org %s / space %s as %s\\.\\.\\.", 170 "my-service", org, space, username)) 171 Eventually(session).Should(Say("FAILED")) 172 Eventually(session.Err).Should(Say("Service offering 'some-service' not found")) 173 Eventually(session).Should(Exit(1)) 174 }) 175 }) 176 177 When("the service provided is accessible", func() { 178 var ( 179 service string 180 servicePlan string 181 broker *fakeservicebroker.FakeServiceBroker 182 ) 183 184 BeforeEach(func() { 185 broker = fakeservicebroker.New().EnsureBrokerIsAvailable() 186 service = broker.ServiceName() 187 servicePlan = broker.ServicePlanName() 188 189 Eventually(helpers.CF("enable-service-access", service)).Should(Exit(0)) 190 }) 191 192 AfterEach(func() { 193 broker.Destroy() 194 }) 195 196 It("displays an informative success message, exits 0", func() { 197 By("creating the service") 198 session := helpers.CF("create-service", service, servicePlan, "my-service") 199 Eventually(session).Should(Say("Creating service instance %s in org %s / space %s as %s\\.\\.\\.", 200 "my-service", org, space, username)) 201 Eventually(session).Should(Say("OK")) 202 Eventually(session).Should(Exit(0)) 203 204 session = helpers.CF("services") 205 Eventually(session).Should(Exit(0)) 206 Eventually(session).Should(Say("%s\\s+%s\\s+%s\\s+create succeeded", 207 "my-service", 208 service, 209 servicePlan, 210 )) 211 212 By("displaying the service already exists when using a duplicate name") 213 session = helpers.CF("create-service", service, servicePlan, "my-service") 214 Eventually(session).Should(Say("OK")) 215 Eventually(session).Should(Say("Service my-service already exists")) 216 Eventually(session).Should(Exit(0)) 217 }) 218 219 When("the provided plan does not exist", func() { 220 It("displays an informative error message, exits 1", func() { 221 session := helpers.CF("create-service", service, "some-plan", "service-instance") 222 Eventually(session).Should(Say("Creating service instance %s in org %s / space %s as %s\\.\\.\\.", 223 "service-instance", org, space, username)) 224 Eventually(session).Should(Say("FAILED")) 225 Eventually(session.Err).Should(Say("The plan %s could not be found for service %s", "some-plan", service)) 226 Eventually(session).Should(Exit(1)) 227 }) 228 }) 229 230 When("creating with valid params json", func() { 231 It("displays an informative success message, exits 0", func() { 232 session := helpers.CF("create-service", service, servicePlan, "my-service", "-c", "{}") 233 Eventually(session).Should(Say("Creating service instance %s in org %s / space %s as %s\\.\\.\\.", 234 "my-service", org, space, username)) 235 Eventually(session).Should(Say("OK")) 236 Eventually(session).Should(Exit(0)) 237 238 session = helpers.CF("services") 239 Eventually(session).Should(Exit(0)) 240 Eventually(session).Should(Say("%s\\s+%s\\s+%s\\s+create succeeded", 241 "my-service", 242 service, 243 servicePlan, 244 )) 245 }) 246 }) 247 248 When("creating with valid params json in a file", func() { 249 var tempFilePath string 250 251 BeforeEach(func() { 252 tempFilePath = helpers.TempFileWithContent(`{"valid":"json"}`) 253 }) 254 255 AfterEach(func() { 256 Expect(os.Remove(tempFilePath)).To(Succeed()) 257 }) 258 259 It("displays an informative success message, exits 0", func() { 260 session := helpers.CF("create-service", service, servicePlan, "my-service", "-c", tempFilePath) 261 Eventually(session).Should(Say("Creating service instance %s in org %s / space %s as %s\\.\\.\\.", 262 "my-service", org, space, username)) 263 Eventually(session).Should(Say("OK")) 264 Eventually(session).Should(Exit(0)) 265 266 session = helpers.CF("services") 267 Eventually(session).Should(Exit(0)) 268 Eventually(session).Should(Say("%s\\s+%s\\s+%s\\s+create succeeded", 269 "my-service", 270 service, 271 servicePlan, 272 )) 273 }) 274 }) 275 276 When("creating with tags", func() { 277 It("displays an informative message, exits 0, and creates the service with tags", func() { 278 session := helpers.CF("create-service", service, servicePlan, "my-service", "-t", "sapi, rocks") 279 Eventually(session).Should(Say("Creating service instance %s in org %s / space %s as %s\\.\\.\\.", 280 "my-service", org, space, username)) 281 Eventually(session).Should(Say("OK")) 282 Eventually(session).Should(Exit(0)) 283 284 session = helpers.CF("service", "my-service") 285 Eventually(session).Should(Exit(0)) 286 Eventually(session).Should(Say("tags:\\s+sapi, rocks")) 287 }) 288 }) 289 }) 290 291 When("the service provided is async and accessible", func() { 292 var ( 293 service string 294 servicePlan string 295 broker *fakeservicebroker.FakeServiceBroker 296 ) 297 298 BeforeEach(func() { 299 broker = fakeservicebroker.New().WithAsyncBehaviour().EnsureBrokerIsAvailable() 300 service = broker.ServiceName() 301 servicePlan = broker.ServicePlanName() 302 Eventually(helpers.CF("enable-service-access", service)).Should(Exit(0)) 303 }) 304 305 AfterEach(func() { 306 broker.Destroy() 307 }) 308 309 It("creates the service and displays a message that creation is in progress", func() { 310 session := helpers.CF("create-service", service, servicePlan, "my-service") 311 Eventually(session).Should(Say("Creating service instance %s in org %s / space %s as %s\\.\\.\\.", 312 "my-service", org, space, username)) 313 Eventually(session).Should(Say("OK")) 314 Eventually(session).Should(Say("Create in progress. Use 'cf services' or 'cf service my-service' to check operation status.")) 315 Eventually(session).Should(Exit(0)) 316 }) 317 }) 318 319 When("there are two services with the same name from different brokers", func() { 320 var ( 321 service string 322 servicePlan string 323 broker1 *fakeservicebroker.FakeServiceBroker 324 broker2 *fakeservicebroker.FakeServiceBroker 325 ) 326 327 BeforeEach(func() { 328 helpers.SkipIfVersionLessThan(ccversion.MinVersionMultiServiceRegistrationV2) 329 330 broker1 = fakeservicebroker.New().EnsureBrokerIsAvailable() 331 service = broker1.ServiceName() 332 servicePlan = broker1.ServicePlanName() 333 broker2 = fakeservicebroker.NewAlternate() 334 broker2.Services[0].Name = service 335 broker2.Services[0].Plans[0].Name = servicePlan 336 broker2.EnsureBrokerIsAvailable() 337 338 Eventually(helpers.CF("enable-service-access", service, "-b", broker1.Name())).Should(Exit(0)) 339 Eventually(helpers.CF("enable-service-access", service, "-b", broker2.Name())).Should(Exit(0)) 340 }) 341 342 AfterEach(func() { 343 broker1.Destroy() 344 broker2.Destroy() 345 }) 346 347 When("the user does not specify which broker to use", func() { 348 It("displays an informative error message, exits 1", func() { 349 session := helpers.CF("create-service", service, servicePlan, "my-service") 350 Eventually(session).Should(Say("Creating service instance %s in org %s / space %s as %s\\.\\.\\.", 351 "my-service", org, space, username)) 352 Eventually(session.Err).Should(Say("Service '%s' is provided by multiple service brokers\\. Specify a broker by using the '-b' flag\\.", service)) 353 Eventually(session).Should(Say("FAILED")) 354 Eventually(session).Should(Exit(1)) 355 }) 356 }) 357 358 When("the user specifies which broker to use", func() { 359 When("the user is a space developer", func() { 360 BeforeEach(func() { 361 username = helpers.SwitchToSpaceRole(org, space, "SpaceDeveloper") 362 helpers.TargetOrgAndSpace(org, space) 363 }) 364 365 AfterEach(func() { 366 helpers.SetupCF(org, space) 367 }) 368 369 It("displays an informative success message, exits 0", func() { 370 By("creating the service with -b flag") 371 session := helpers.CF("create-service", service, servicePlan, "my-service", "-b", broker1.Name()) 372 Eventually(session).Should(Say("Creating service instance %s in org %s / space %s as %s\\.\\.\\.", 373 "my-service", org, space, username)) 374 Eventually(session).Should(Say("OK")) 375 Eventually(session).Should(Exit(0)) 376 377 session = helpers.CF("services") 378 Eventually(session).Should(Exit(0)) 379 Eventually(session).Should(Say("%s\\s+%s\\s+%s\\s+create succeeded", 380 "my-service", 381 service, 382 servicePlan, 383 )) 384 }) 385 386 Context("the broker is not accessible by that user", func() { 387 It("displays an informative error message, exits 1", func() { 388 session := helpers.CF("create-service", service, servicePlan, "my-service", "-b", "non-existent-broker") 389 Eventually(session).Should(Say("Creating service instance %s in org %s / space %s as %s\\.\\.\\.", 390 "my-service", org, space, username)) 391 Eventually(session.Err).Should(Say("Service '%s' provided by service broker '%s' not found\\.", service, "non-existent-broker")) 392 Eventually(session).Should(Say("FAILED")) 393 Eventually(session).Should(Exit(1)) 394 }) 395 }) 396 }) 397 }) 398 }) 399 }) 400 }) 401 })