github.com/arunkumar7540/cli@v6.45.0+incompatible/integration/shared/isolated/bind_service_command_test.go (about) 1 package isolated 2 3 import ( 4 "io/ioutil" 5 "os" 6 "path/filepath" 7 "time" 8 9 "code.cloudfoundry.org/cli/api/cloudcontroller/ccversion" 10 "code.cloudfoundry.org/cli/integration/helpers" 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("bind-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("bind-service", "--help") 22 Eventually(session).Should(Say("NAME:")) 23 Eventually(session).Should(Say("bind-service - Bind a service instance to an app")) 24 25 Eventually(session).Should(Say("USAGE:")) 26 Eventually(session).Should(Say("cf bind-service APP_NAME SERVICE_INSTANCE \\[-c PARAMETERS_AS_JSON\\] \\[--binding-name BINDING_NAME\\]")) 27 Eventually(session).Should(Say("Optionally provide service-specific configuration parameters in a valid JSON object in-line:")) 28 Eventually(session).Should(Say("cf bind-service APP_NAME SERVICE_INSTANCE -c '{\"name\":\"value\",\"name\":\"value\"}'")) 29 Eventually(session).Should(Say("Optionally provide a file containing service-specific configuration parameters in a valid JSON object.")) 30 Eventually(session).Should(Say("The path to the parameters file can be an absolute or relative path to a file.")) 31 Eventually(session).Should(Say("cf bind-service APP_NAME SERVICE_INSTANCE -c PATH_TO_FILE")) 32 Eventually(session).Should(Say("Example of valid JSON object:")) 33 Eventually(session).Should(Say("{")) 34 Eventually(session).Should(Say("\"permissions\": \"read-only\"")) 35 Eventually(session).Should(Say("}")) 36 Eventually(session).Should(Say("Optionally provide a binding name for the association between an app and a service instance:")) 37 Eventually(session).Should(Say("cf bind-service APP_NAME SERVICE_INSTANCE --binding-name BINDING_NAME")) 38 Eventually(session).Should(Say("EXAMPLES:")) 39 Eventually(session).Should(Say("Linux/Mac:")) 40 Eventually(session).Should(Say("cf bind-service myapp mydb -c '{\"permissions\":\"read-only\"}'")) 41 Eventually(session).Should(Say("Windows Command Line:")) 42 Eventually(session).Should(Say("cf bind-service myapp mydb -c \"{\\\\\"permissions\\\\\":\\\\\"read-only\\\\\"}\"")) 43 Eventually(session).Should(Say("Windows PowerShell:")) 44 Eventually(session).Should(Say("cf bind-service myapp mydb -c '{\\\\\"permissions\\\\\":\\\\\"read-only\\\\\"}'")) 45 Eventually(session).Should(Say("cf bind-service myapp mydb -c ~/workspace/tmp/instance_config.json --binding-name BINDING_NAME")) 46 Eventually(session).Should(Say("ALIAS:")) 47 Eventually(session).Should(Say("bs")) 48 Eventually(session).Should(Say("OPTIONS:")) 49 Eventually(session).Should(Say("--binding-name\\s+Name to expose service instance to app process with \\(Default: service instance name\\)")) 50 Eventually(session).Should(Say("-c\\s+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.")) 51 Eventually(session).Should(Say("SEE ALSO:")) 52 Eventually(session).Should(Say("services")) 53 Eventually(session).Should(Exit(0)) 54 }) 55 }) 56 }) 57 58 var ( 59 serviceInstance string 60 appName string 61 ) 62 63 BeforeEach(func() { 64 serviceInstance = helpers.PrefixedRandomName("si") 65 appName = helpers.PrefixedRandomName("app") 66 }) 67 68 When("the environment is not setup correctly", func() { 69 It("fails with the appropriate errors", func() { 70 helpers.CheckEnvironmentTargetedCorrectly(true, true, ReadOnlyOrg, "bind-service", "app-name", "service-name") 71 }) 72 }) 73 74 When("provided invalid flag values", func() { 75 When("the --binding-name flag is provided and its value is the empty string", func() { 76 It("returns an invalid usage error and the help text", func() { 77 session := helpers.CF("bind-service", appName, serviceInstance, "--binding-name", "") 78 Eventually(session.Err).Should(Say("--binding-name must be at least 1 character in length")) 79 80 Eventually(session).Should(Say("NAME:")) 81 Eventually(session).Should(Exit(1)) 82 }) 83 }) 84 }) 85 86 When("the environment is setup correctly", func() { 87 var ( 88 org string 89 space string 90 service string 91 servicePlan string 92 domain string 93 username string 94 ) 95 96 BeforeEach(func() { 97 org = helpers.NewOrgName() 98 space = helpers.NewSpaceName() 99 service = helpers.PrefixedRandomName("SERVICE") 100 servicePlan = helpers.PrefixedRandomName("SERVICE-PLAN") 101 username, _ = helpers.GetCredentials() 102 103 helpers.SetupCF(org, space) 104 domain = helpers.DefaultSharedDomain() 105 }) 106 107 AfterEach(func() { 108 helpers.QuickDeleteOrg(org) 109 }) 110 111 When("the app does not exist", func() { 112 It("displays FAILED and app not found", func() { 113 session := helpers.CF("bind-service", "does-not-exist", serviceInstance) 114 Eventually(session).Should(Say("FAILED")) 115 Eventually(session.Err).Should(Say("App '%s' not found", "does-not-exist")) 116 Eventually(session).Should(Exit(1)) 117 }) 118 }) 119 120 When("the app exists", func() { 121 BeforeEach(func() { 122 helpers.WithHelloWorldApp(func(appDir string) { 123 Eventually(helpers.CF("push", appName, "--no-start", "-p", appDir, "-b", "staticfile_buildpack", "--no-route")).Should(Exit(0)) 124 }) 125 }) 126 127 When("the service does not exist", func() { 128 It("displays FAILED and service not found", func() { 129 session := helpers.CF("bind-service", appName, "does-not-exist") 130 Eventually(session).Should(Say("FAILED")) 131 Eventually(session.Err).Should(Say("Service instance %s not found", "does-not-exist")) 132 Eventually(session).Should(Exit(1)) 133 }) 134 }) 135 136 When("the service exists", func() { 137 BeforeEach(func() { 138 Eventually(helpers.CF("create-user-provided-service", serviceInstance, "-p", "{}")).Should(Exit(0)) 139 helpers.WithHelloWorldApp(func(appDir string) { 140 Eventually(helpers.CF("push", appName, "--no-start", "-p", appDir, "-b", "staticfile_buildpack", "--no-route")).Should(Exit(0)) 141 }) 142 }) 143 144 AfterEach(func() { 145 Eventually(helpers.CF("unbind-service", appName, serviceInstance)).Should(Exit(0)) 146 Eventually(helpers.CF("delete-service", serviceInstance, "-f")).Should(Exit(0)) 147 }) 148 149 It("binds the service to the app, displays OK and TIP", func() { 150 session := helpers.CF("bind-service", appName, serviceInstance) 151 Eventually(session).Should(Say("Binding service %s to app %s in org %s / space %s as %s...", serviceInstance, appName, org, space, username)) 152 153 Eventually(session).Should(Say("OK")) 154 Eventually(session).Should(Say("TIP: Use 'cf restage %s' to ensure your env variable changes take effect", appName)) 155 Eventually(session).Should(Exit(0)) 156 }) 157 158 When("the service is already bound to an app", func() { 159 BeforeEach(func() { 160 Eventually(helpers.CF("bind-service", appName, serviceInstance)).Should(Exit(0)) 161 }) 162 163 It("displays OK and that the app is already bound to the service", func() { 164 session := helpers.CF("bind-service", appName, serviceInstance) 165 166 Eventually(session).Should(Say("Binding service %s to app %s in org %s / space %s as %s...", serviceInstance, appName, org, space, username)) 167 Eventually(session).Should(Say("App %s is already bound to %s.", appName, serviceInstance)) 168 Eventually(session).Should(Say("OK")) 169 170 Eventually(session).Should(Exit(0)) 171 }) 172 }) 173 174 When("the --binding-name flag is provided and the value is a non-empty string", func() { 175 It("binds the service to the app, displays OK and TIP", func() { 176 session := helpers.CF("bind-service", appName, serviceInstance, "--binding-name", "i-am-a-binding") 177 Eventually(session.Out).Should(Say("Binding service %s to app %s with binding name %s in org %s / space %s as %s...", serviceInstance, appName, "i-am-a-binding", org, space, username)) 178 179 Eventually(session.Out).Should(Say("OK")) 180 Eventually(session.Out).Should(Say("TIP: Use 'cf restage %s' to ensure your env variable changes take effect", appName)) 181 Eventually(session).Should(Exit(0)) 182 }) 183 }) 184 185 When("configuration parameters are provided in a file", func() { 186 var configurationFile *os.File 187 188 When("the file-path does not exist", func() { 189 It("displays FAILED and the invalid configuration error", func() { 190 session := helpers.CF("bind-service", appName, serviceInstance, "-c", "i-do-not-exist") 191 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.")) 192 193 Eventually(session).Should(Exit(1)) 194 }) 195 }) 196 197 When("the file contians invalid json", func() { 198 BeforeEach(func() { 199 var err error 200 content := []byte("{i-am-very-bad-json") 201 configurationFile, err = ioutil.TempFile("", "CF_CLI") 202 Expect(err).ToNot(HaveOccurred()) 203 204 _, err = configurationFile.Write(content) 205 Expect(err).ToNot(HaveOccurred()) 206 207 err = configurationFile.Close() 208 Expect(err).ToNot(HaveOccurred()) 209 }) 210 211 AfterEach(func() { 212 Expect(os.RemoveAll(configurationFile.Name())).ToNot(HaveOccurred()) 213 }) 214 215 It("displays FAILED and the invalid configuration error", func() { 216 session := helpers.CF("bind-service", appName, serviceInstance, "-c", configurationFile.Name()) 217 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.")) 218 219 Eventually(session).Should(Exit(1)) 220 }) 221 }) 222 223 When("the file-path is relative", func() { 224 BeforeEach(func() { 225 var err error 226 content := []byte("{\"i-am-good-json\":\"good-boy\"}") 227 configurationFile, err = ioutil.TempFile("", "CF_CLI") 228 Expect(err).ToNot(HaveOccurred()) 229 230 _, err = configurationFile.Write(content) 231 Expect(err).ToNot(HaveOccurred()) 232 233 err = configurationFile.Close() 234 Expect(err).ToNot(HaveOccurred()) 235 }) 236 237 AfterEach(func() { 238 Expect(os.RemoveAll(configurationFile.Name())).ToNot(HaveOccurred()) 239 }) 240 241 It("binds the service to the app, displays OK and TIP", func() { 242 session := helpers.CF("bind-service", appName, serviceInstance, "-c", configurationFile.Name()) 243 Eventually(session).Should(Say("Binding service %s to app %s in org %s / space %s as %s...", serviceInstance, appName, org, space, username)) 244 245 Eventually(session).Should(Say("OK")) 246 Eventually(session).Should(Say("TIP: Use 'cf restage %s' to ensure your env variable changes take effect", appName)) 247 Eventually(session).Should(Exit(0)) 248 }) 249 }) 250 251 When("the file-path is absolute", func() { 252 BeforeEach(func() { 253 var err error 254 content := []byte("{\"i-am-good-json\":\"good-boy\"}") 255 configurationFile, err = ioutil.TempFile("", "CF_CLI") 256 Expect(err).ToNot(HaveOccurred()) 257 258 _, err = configurationFile.Write(content) 259 Expect(err).ToNot(HaveOccurred()) 260 261 err = configurationFile.Close() 262 Expect(err).ToNot(HaveOccurred()) 263 }) 264 265 AfterEach(func() { 266 Expect(os.RemoveAll(configurationFile.Name())).ToNot(HaveOccurred()) 267 }) 268 269 It("binds the service to the app, displays OK and TIP", func() { 270 absolutePath, err := filepath.Abs(configurationFile.Name()) 271 Expect(err).ToNot(HaveOccurred()) 272 session := helpers.CF("bind-service", appName, serviceInstance, "-c", absolutePath) 273 Eventually(session).Should(Say("Binding service %s to app %s in org %s / space %s as %s...", serviceInstance, appName, org, space, username)) 274 275 Eventually(session).Should(Say("OK")) 276 Eventually(session).Should(Say("TIP: Use 'cf restage %s' to ensure your env variable changes take effect", appName)) 277 Eventually(session).Should(Exit(0)) 278 }) 279 }) 280 }) 281 282 When("configuration paramters are provided as in-line JSON", func() { 283 When("the JSON is invalid", func() { 284 It("displays FAILED and the invalid configuration error", func() { 285 session := helpers.CF("bind-service", appName, serviceInstance, "-c", "i-am-invalid-json") 286 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.")) 287 288 Eventually(session).Should(Exit(1)) 289 }) 290 }) 291 292 When("the JSON is valid", func() { 293 It("binds the service to the app, displays OK and TIP", func() { 294 session := helpers.CF("bind-service", appName, serviceInstance, "-c", "{\"i-am-valid-json\":\"dope dude\"}") 295 Eventually(session).Should(Say("Binding service %s to app %s in org %s / space %s as %s...", serviceInstance, appName, org, space, username)) 296 297 Eventually(session).Should(Say("OK")) 298 Eventually(session).Should(Say("TIP: Use 'cf restage %s' to ensure your env variable changes take effect", appName)) 299 Eventually(session).Should(Exit(0)) 300 }) 301 }) 302 }) 303 }) 304 305 When("the service is provided by a broker", func() { 306 307 When("the service binding is blocking", func() { 308 var broker helpers.ServiceBroker 309 310 BeforeEach(func() { 311 broker = helpers.CreateBroker(domain, service, servicePlan) 312 313 Eventually(helpers.CF("enable-service-access", service)).Should(Exit(0)) 314 Eventually(helpers.CF("create-service", service, servicePlan, serviceInstance)).Should(Exit(0)) 315 }) 316 317 AfterEach(func() { 318 broker.Destroy() 319 }) 320 321 It("binds the service to the app, displays OK and TIP", func() { 322 session := helpers.CF("bind-service", appName, serviceInstance, "-c", `{"wheres":"waldo"}`) 323 Eventually(session).Should(Say("Binding service %s to app %s in org %s / space %s as %s...", serviceInstance, appName, org, space, username)) 324 325 Eventually(session).Should(Say("OK")) 326 Eventually(session).Should(Say("TIP: Use 'cf restage %s' to ensure your env variable changes take effect", appName)) 327 Eventually(session).Should(Exit(0)) 328 329 session = helpers.CF("service", serviceInstance) 330 Eventually(session).Should(Say(appName)) 331 Eventually(session).Should(Exit(0)) 332 }) 333 }) 334 335 When("the service binding is asynchronous", func() { 336 var broker helpers.ServiceBroker 337 338 BeforeEach(func() { 339 helpers.SkipIfVersionLessThan(ccversion.MinVersionAsyncBindingsV2) 340 341 broker = helpers.CreateAsyncBroker(domain, service, servicePlan) 342 343 Eventually(helpers.CF("enable-service-access", service)).Should(Exit(0)) 344 Eventually(helpers.CF("create-service", service, servicePlan, serviceInstance)).Should(Exit(0)) 345 346 Eventually(func() *Session { 347 session := helpers.CF("service", serviceInstance) 348 return session.Wait() 349 }, time.Minute*5, time.Second*5).Should(Say("create succeeded")) 350 }) 351 352 AfterEach(func() { 353 broker.Destroy() 354 }) 355 356 It("binds the service to the app, displays OK and TIP", func() { 357 session := helpers.CF("bind-service", appName, serviceInstance, "-c", `{"wheres":"waldo"}`) 358 Eventually(session).Should(Say("Binding service %s to app %s in org %s / space %s as %s...", serviceInstance, appName, org, space, username)) 359 360 Eventually(session).Should(Say("OK")) 361 Eventually(session).Should(Say("Binding in progress. Use 'cf service %s' to check operation status.", serviceInstance)) 362 Eventually(session).Should(Say("TIP: Once this operation succeeds, use 'cf restage %s' to ensure your env variable changes take effect", appName)) 363 Eventually(session).Should(Exit(0)) 364 365 session = helpers.CF("service", serviceInstance) 366 Eventually(session).Should(Say(appName)) 367 Eventually(session).Should(Exit(0)) 368 }) 369 }) 370 }) 371 }) 372 }) 373 })