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