github.com/DaAlbrecht/cf-cli@v0.0.0-20231128151943-1fe19bb400b9/integration/v7/isolated/service_command_test.go (about)

     1  package isolated
     2  
     3  import (
     4  	"fmt"
     5  	"strings"
     6  	"time"
     7  
     8  	"code.cloudfoundry.org/cli/integration/helpers"
     9  	"code.cloudfoundry.org/cli/integration/helpers/servicebrokerstub"
    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("service command", func() {
    17  	const serviceCommand = "service"
    18  
    19  	Describe("help", func() {
    20  		const serviceInstanceName = "fake-service-instance-name"
    21  
    22  		matchHelpMessage := SatisfyAll(
    23  			Say(`NAME:\n`),
    24  			Say(fmt.Sprintf(`\s+%s - Show service instance info\n`, serviceCommand)),
    25  			Say(`\n`),
    26  			Say(`USAGE:\n`),
    27  			Say(`\s+cf service SERVICE_INSTANCE\n`),
    28  			Say(`\n`),
    29  			Say(`OPTIONS:\n`),
    30  			Say(`\s+--guid\s+Retrieve and display the given service instances's guid. All other output is suppressed.\n`),
    31  			Say(`\s+--params\s+Retrieve and display the given service instances's parameters. All other output is suppressed.\n`),
    32  			Say(`\n`),
    33  			Say(`SEE ALSO:\n`),
    34  			Say(`\s+bind-service, rename-service, update-service\n`),
    35  			Say(`$`),
    36  		)
    37  
    38  		When("the -h flag is specified", func() {
    39  			It("succeeds and prints help", func() {
    40  				session := helpers.CF(serviceCommand, serviceInstanceName, "-h")
    41  				Eventually(session).Should(Exit(0))
    42  				Expect(session.Out).To(matchHelpMessage)
    43  			})
    44  		})
    45  
    46  		When("the service instance name is missing", func() {
    47  			It("fails with an error and prints help", func() {
    48  				session := helpers.CF(serviceCommand)
    49  				Eventually(session).Should(Exit(1))
    50  				Expect(session.Err).To(Say("Incorrect Usage: the required argument `SERVICE_INSTANCE` was not provided"))
    51  				Expect(session.Out).To(matchHelpMessage)
    52  			})
    53  		})
    54  
    55  		When("an extra parameter is specified", func() {
    56  			It("fails with an error and prints help", func() {
    57  				session := helpers.CF(serviceCommand, serviceInstanceName, "anotherRandomParameter")
    58  				Eventually(session).Should(Exit(1))
    59  				Expect(session.Err).To(Say(`Incorrect Usage: unexpected argument "anotherRandomParameter"`))
    60  				Expect(session.Out).To(SatisfyAll(
    61  					Say(`FAILED\n\n`),
    62  					matchHelpMessage,
    63  				))
    64  			})
    65  		})
    66  
    67  		When("an extra flag is specified", func() {
    68  			It("fails with an error and prints help", func() {
    69  				session := helpers.CF(serviceCommand, serviceInstanceName, "--anotherRandomFlag")
    70  				Eventually(session).Should(Exit(1))
    71  				Expect(session.Err).To(Say("Incorrect Usage: unknown flag `anotherRandomFlag'"))
    72  				Expect(session.Out).To(matchHelpMessage)
    73  			})
    74  		})
    75  	})
    76  
    77  	When("environment is not set up", func() {
    78  		It("displays an error and exits 1", func() {
    79  			helpers.CheckEnvironmentTargetedCorrectly(true, true, ReadOnlyOrg, serviceCommand, "serviceInstanceName")
    80  		})
    81  	})
    82  
    83  	When("user is logged in and targeting a space", func() {
    84  		var (
    85  			serviceInstanceName string
    86  			orgName             string
    87  			spaceName           string
    88  		)
    89  
    90  		BeforeEach(func() {
    91  			orgName = helpers.NewOrgName()
    92  			spaceName = helpers.NewSpaceName()
    93  			helpers.SetupCF(orgName, spaceName)
    94  
    95  			serviceInstanceName = helpers.NewServiceInstanceName()
    96  		})
    97  
    98  		AfterEach(func() {
    99  			helpers.QuickDeleteOrg(orgName)
   100  		})
   101  
   102  		When("the service instance is user-provided", func() {
   103  			const (
   104  				routeServiceURL = "https://route.com"
   105  				syslogURL       = "https://syslog.com"
   106  				tags            = "foo, bar"
   107  			)
   108  
   109  			BeforeEach(func() {
   110  				command := []string{
   111  					"create-user-provided-service", serviceInstanceName,
   112  					"-r", routeServiceURL,
   113  					"-l", syslogURL,
   114  					"-t", tags,
   115  				}
   116  				Eventually(helpers.CF(command...)).Should(Exit(0))
   117  			})
   118  
   119  			It("can show the GUID", func() {
   120  				session := helpers.CF(serviceCommand, serviceInstanceName, "--guid")
   121  				Eventually(session).Should(Exit(0))
   122  				Expect(strings.TrimSpace(string(session.Out.Contents()))).To(HaveLen(36), "GUID wrong length")
   123  			})
   124  
   125  			It("can show the service instance details", func() {
   126  				session := helpers.CF(serviceCommand, serviceInstanceName)
   127  				Eventually(session).Should(Exit(0))
   128  
   129  				username, _ := helpers.GetCredentials()
   130  				Expect(session).To(SatisfyAll(
   131  					Say(`Showing info of service %s in org %s / space %s as %s...\n`, serviceInstanceName, orgName, spaceName, username),
   132  					Say(`\n`),
   133  					Say(`name:\s+%s\n`, serviceInstanceName),
   134  					Say(`guid:\s+\S{36}\n`),
   135  					Say(`type:\s+user-provided`),
   136  					Say(`tags:\s+%s\n`, tags),
   137  					Say(`route service url:\s+%s\n`, routeServiceURL),
   138  					Say(`syslog drain url:\s+%s\n`, syslogURL),
   139  					Say(`\n`),
   140  					Say(`Showing status of last operation:\n`),
   141  					Say(`status:\s+create succeeded\n`),
   142  					Say(`message:\s+Operation succeeded\n`),
   143  					Say(`started:\s+%s\n`, helpers.TimestampRegex),
   144  					Say(`updated:\s+%s\n`, helpers.TimestampRegex),
   145  					Say(`\n`),
   146  					Say(`Showing bound apps:\n`),
   147  					Say(`There are no bound apps for this service instance\.\n`),
   148  				))
   149  			})
   150  
   151  			When("bound to apps", func() {
   152  				var (
   153  					appName1     string
   154  					appName2     string
   155  					bindingName1 string
   156  					bindingName2 string
   157  				)
   158  
   159  				BeforeEach(func() {
   160  					appName1 = helpers.PrefixedRandomName("APP1")
   161  					appName2 = helpers.PrefixedRandomName("APP2")
   162  					bindingName1 = helpers.RandomName()
   163  					bindingName2 = helpers.RandomName()
   164  
   165  					helpers.WithHelloWorldApp(func(appDir string) {
   166  						Eventually(helpers.CF("push", appName1, "--no-start", "-p", appDir, "-b", "staticfile_buildpack", "--no-route")).Should(Exit(0))
   167  						Eventually(helpers.CF("push", appName2, "--no-start", "-p", appDir, "-b", "staticfile_buildpack", "--no-route")).Should(Exit(0))
   168  					})
   169  					Eventually(helpers.CF("bind-service", appName1, serviceInstanceName, "--binding-name", bindingName1)).Should(Exit(0))
   170  					Eventually(helpers.CF("bind-service", appName2, serviceInstanceName, "--binding-name", bindingName2)).Should(Exit(0))
   171  				})
   172  
   173  				It("displays the bound apps", func() {
   174  					//Delay to reduce flakiness
   175  					time.Sleep(10 * time.Second)
   176  					session := helpers.CF(serviceCommand, serviceInstanceName, "-v")
   177  					Eventually(session).Should(Exit(0))
   178  
   179  					Expect(session).To(SatisfyAll(
   180  						Say(`Showing bound apps:\n`),
   181  						Say(`name\s+binding name\s+status\s+message\n`),
   182  						Say(`%s\s+%s\s+create succeeded\s*\n`, appName1, bindingName1),
   183  						Say(`%s\s+%s\s+create succeeded\s*\n`, appName2, bindingName2),
   184  					))
   185  				})
   186  			})
   187  
   188  			When("--params is requested", func() {
   189  				When("service instance parameters have been set", func() {
   190  					It("reports the service instance parameters JSON", func() {
   191  						session := helpers.CF(serviceCommand, serviceInstanceName, "--params")
   192  						Eventually(session).Should(Exit(1))
   193  
   194  						Eventually(session.Err).Should(Say("This service does not support fetching service instance parameters."))
   195  					})
   196  				})
   197  			})
   198  
   199  		})
   200  
   201  		When("the service instance is managed by a broker", func() {
   202  			const (
   203  				testPollingInterval = time.Second
   204  				testTimeout         = time.Minute
   205  			)
   206  
   207  			var broker *servicebrokerstub.ServiceBrokerStub
   208  
   209  			AfterEach(func() {
   210  				broker.Forget()
   211  			})
   212  
   213  			When("created successfully", func() {
   214  				const tags = "foo, bar"
   215  
   216  				BeforeEach(func() {
   217  					broker = servicebrokerstub.New().WithAsyncDelay(time.Nanosecond).EnableServiceAccess()
   218  
   219  					helpers.CreateManagedServiceInstance(
   220  						broker.FirstServiceOfferingName(),
   221  						broker.FirstServicePlanName(),
   222  						serviceInstanceName,
   223  						"-t", tags,
   224  					)
   225  				})
   226  
   227  				It("can show the service instance details", func() {
   228  					session := helpers.CF(serviceCommand, serviceInstanceName)
   229  					Eventually(session).Should(Exit(0))
   230  
   231  					username, _ := helpers.GetCredentials()
   232  					Expect(session).To(SatisfyAll(
   233  						Say(`Showing info of service %s in org %s / space %s as %s...\n`, serviceInstanceName, orgName, spaceName, username),
   234  						Say(`\n`),
   235  						Say(`name:\s+%s\n`, serviceInstanceName),
   236  						Say(`guid:\s+\S+\n`),
   237  						Say(`type:\s+managed`),
   238  						Say(`broker:\s+%s`, broker.Name),
   239  						Say(`offering:\s+%s`, broker.FirstServiceOfferingName()),
   240  						Say(`plan:\s+%s`, broker.FirstServicePlanName()),
   241  						Say(`tags:\s+%s\n`, tags),
   242  						Say(`offering tags:\s+%s\n`, strings.Join(broker.Services[0].Tags, ", ")),
   243  						Say(`description:\s+%s\n`, broker.Services[0].Description),
   244  						Say(`documentation:\s+%s\n`, broker.Services[0].DocumentationURL),
   245  						Say(`dashboard url:\s+http://example.com\n`),
   246  						Say(`\n`),
   247  						Say(`Showing status of last operation:\n`),
   248  						Say(`status:\s+create succeeded\n`),
   249  						Say(`message:\s+very happy service\n`),
   250  						Say(`started:\s+%s\n`, helpers.TimestampRegex),
   251  						Say(`updated:\s+%s\n`, helpers.TimestampRegex),
   252  						Say(`\n`),
   253  						Say(`Showing bound apps:\n`),
   254  						Say(`There are no bound apps for this service instance\.\n`),
   255  						Say(`\n`),
   256  						Say(`Showing sharing info:\n`),
   257  						Say(`This service instance is not currently being shared.`),
   258  						Say(`\n`),
   259  						Say(`Upgrades are not supported by this broker.\n`),
   260  					))
   261  				})
   262  			})
   263  
   264  			When("creation is in progress", func() {
   265  				const (
   266  					tags             = "foo, bar"
   267  					brokerAsyncDelay = time.Second
   268  				)
   269  
   270  				BeforeEach(func() {
   271  					broker = servicebrokerstub.New().WithAsyncDelay(brokerAsyncDelay).EnableServiceAccess()
   272  					command := []string{
   273  						"create-service",
   274  						broker.FirstServiceOfferingName(),
   275  						broker.FirstServicePlanName(),
   276  						serviceInstanceName,
   277  						"-t", tags,
   278  					}
   279  					Eventually(helpers.CF(command...)).Should(Exit(0))
   280  				})
   281  
   282  				It("can show the GUID immediately", func() {
   283  					session := helpers.CF(serviceCommand, serviceInstanceName, "--guid")
   284  					Eventually(session).Should(Exit(0))
   285  					Expect(strings.TrimSpace(string(session.Out.Contents()))).To(HaveLen(36), "GUID wrong length")
   286  				})
   287  
   288  				It("can show the service instance details", func() {
   289  					session := helpers.CF(serviceCommand, serviceInstanceName)
   290  					Eventually(session).Should(Exit(0))
   291  
   292  					username, _ := helpers.GetCredentials()
   293  					Expect(session).To(SatisfyAll(
   294  						Say(`Showing info of service %s in org %s / space %s as %s...\n`, serviceInstanceName, orgName, spaceName, username),
   295  						Say(`\n`),
   296  						Say(`name:\s+%s\n`, serviceInstanceName),
   297  						Say(`guid:\s+\S+\n`),
   298  						Say(`type:\s+managed`),
   299  						Say(`broker:\s+%s`, broker.Name),
   300  						Say(`offering:\s+%s`, broker.FirstServiceOfferingName()),
   301  						Say(`plan:\s+%s`, broker.FirstServicePlanName()),
   302  						Say(`tags:\s+%s\n`, tags),
   303  						Say(`offering tags:\s+%s\n`, strings.Join(broker.Services[0].Tags, ", ")),
   304  						Say(`description:\s+%s\n`, broker.Services[0].Description),
   305  						Say(`documentation:\s+%s\n`, broker.Services[0].DocumentationURL),
   306  						Say(`dashboard url:\s+http://example.com\n`),
   307  						Say(`\n`),
   308  						Say(`Showing status of last operation:\n`),
   309  						Say(`status:\s+create in progress\n`),
   310  						Say(`message:\s+very happy service\n`),
   311  						Say(`started:\s+%s\n`, helpers.TimestampRegex),
   312  						Say(`updated:\s+%s\n`, helpers.TimestampRegex),
   313  						Say(`\n`),
   314  						Say(`Showing bound apps:\n`),
   315  						Say(`There are no bound apps for this service instance\.\n`),
   316  						Say(`\n`),
   317  						Say(`Showing sharing info:\n`),
   318  						Say(`This service instance is not currently being shared.`),
   319  						Say(`\n`),
   320  						Say(`Showing upgrade status:\n`),
   321  						Say(`Upgrades are not supported by this broker.\n`),
   322  					))
   323  				})
   324  			})
   325  
   326  			When("the instance is shared with another space", func() {
   327  				var sharedToSpaceName string
   328  
   329  				BeforeEach(func() {
   330  					sharedToSpaceName = helpers.NewSpaceName()
   331  					helpers.CreateSpace(sharedToSpaceName)
   332  
   333  					broker = servicebrokerstub.New().EnableServiceAccess()
   334  					command := []string{
   335  						"create-service",
   336  						broker.FirstServiceOfferingName(),
   337  						broker.FirstServicePlanName(),
   338  						serviceInstanceName,
   339  					}
   340  					Eventually(helpers.CF(command...)).Should(Exit(0))
   341  
   342  					output := func() *Buffer {
   343  						session := helpers.CF(serviceCommand, serviceInstanceName)
   344  						session.Wait()
   345  						return session.Out
   346  					}
   347  
   348  					Eventually(output, testTimeout, testPollingInterval).Should(Say(`status:\s+create succeeded\n`))
   349  
   350  					command = []string{
   351  						"share-service",
   352  						serviceInstanceName,
   353  						"-s",
   354  						sharedToSpaceName,
   355  					}
   356  					Eventually(helpers.CF(command...)).Should(Exit(0))
   357  				})
   358  
   359  				AfterEach(func() {
   360  					command := []string{
   361  						"unshare-service",
   362  						serviceInstanceName,
   363  						"-s", sharedToSpaceName,
   364  						"-f",
   365  					}
   366  					Eventually(helpers.CF(command...)).Should(Exit(0))
   367  
   368  					helpers.QuickDeleteSpace(sharedToSpaceName)
   369  				})
   370  
   371  				It("can show that the service is being shared", func() {
   372  					session := helpers.CF(serviceCommand, serviceInstanceName)
   373  					Eventually(session).Should(Exit(0))
   374  
   375  					Expect(session).To(SatisfyAll(
   376  						Say(`Showing sharing info:\n`),
   377  						Say(`Shared with spaces:\n`),
   378  						Say(`org\s+space\s+bindings\n`),
   379  						Say(`%s\s+%s\s+0\s*\n`, orgName, sharedToSpaceName),
   380  					))
   381  				})
   382  			})
   383  
   384  			When("the instance is being accessed form shared to space", func() {
   385  				var sharedToSpaceName string
   386  
   387  				BeforeEach(func() {
   388  					sharedToSpaceName = helpers.NewSpaceName()
   389  					helpers.CreateSpace(sharedToSpaceName)
   390  
   391  					broker = servicebrokerstub.New().EnableServiceAccess()
   392  					command := []string{
   393  						"create-service",
   394  						broker.FirstServiceOfferingName(),
   395  						broker.FirstServicePlanName(),
   396  						serviceInstanceName,
   397  					}
   398  					Eventually(helpers.CF(command...)).Should(Exit(0))
   399  
   400  					output := func() *Buffer {
   401  						session := helpers.CF(serviceCommand, serviceInstanceName)
   402  						session.Wait()
   403  						return session.Out
   404  					}
   405  
   406  					Eventually(output, testTimeout, testPollingInterval).Should(Say(`status:\s+create succeeded\n`))
   407  
   408  					command = []string{
   409  						"share-service",
   410  						serviceInstanceName,
   411  						"-s",
   412  						sharedToSpaceName,
   413  					}
   414  					Eventually(helpers.CF(command...)).Should(Exit(0))
   415  
   416  					helpers.TargetOrgAndSpace(orgName, sharedToSpaceName)
   417  				})
   418  
   419  				AfterEach(func() {
   420  					helpers.TargetOrgAndSpace(orgName, spaceName)
   421  
   422  					command := []string{
   423  						"unshare-service",
   424  						serviceInstanceName,
   425  						"-s", sharedToSpaceName,
   426  						"-f",
   427  					}
   428  					Eventually(helpers.CF(command...)).Should(Exit(0))
   429  
   430  					helpers.QuickDeleteSpace(sharedToSpaceName)
   431  				})
   432  
   433  				It("can show that the service has been shared", func() {
   434  					session := helpers.CF(serviceCommand, serviceInstanceName)
   435  					Eventually(session).Should(Exit(0))
   436  
   437  					Expect(session).To(SatisfyAll(
   438  						Say(`Showing sharing info:\n`),
   439  						Say(`This service instance is shared from space %s of org %s.\n`, spaceName, orgName),
   440  					))
   441  				})
   442  			})
   443  
   444  			When("the broker supports maintenance info", func() {
   445  				When("the service is up to date", func() {
   446  					var serviceInstanceName string
   447  
   448  					BeforeEach(func() {
   449  						serviceInstanceName = helpers.NewServiceInstanceName()
   450  						broker = servicebrokerstub.New().WithMaintenanceInfo("1.2.3").EnableServiceAccess()
   451  						helpers.CreateManagedServiceInstance(broker.FirstServiceOfferingName(), broker.FirstServicePlanName(), serviceInstanceName)
   452  					})
   453  
   454  					It("says that the service has no upgrades available", func() {
   455  						session := helpers.CF(serviceCommand, serviceInstanceName)
   456  						Eventually(session).Should(Exit(0))
   457  
   458  						Expect(session).To(SatisfyAll(
   459  							Say(`Showing upgrade status:\n`),
   460  							Say(`There is no upgrade available for this service.\n`),
   461  						))
   462  					})
   463  				})
   464  
   465  				When("an update is available", func() {
   466  					var serviceInstanceName string
   467  
   468  					BeforeEach(func() {
   469  						serviceInstanceName = helpers.NewServiceInstanceName()
   470  						broker = servicebrokerstub.New().WithMaintenanceInfo("1.2.3").EnableServiceAccess()
   471  						helpers.CreateManagedServiceInstance(broker.FirstServiceOfferingName(), broker.FirstServicePlanName(), serviceInstanceName)
   472  
   473  						broker.WithMaintenanceInfo("1.2.4", "really cool improvement").Configure().Register()
   474  					})
   475  
   476  					It("displays information about the upgrade", func() {
   477  						session := helpers.CF(serviceCommand, serviceInstanceName)
   478  						Eventually(session).Should(Exit(0))
   479  
   480  						Expect(session).To(SatisfyAll(
   481  							Say(`Showing upgrade status:\n`),
   482  							Say(`There is an upgrade available for this service.\n`),
   483  							Say(`Upgrade description: really cool improvement\n`),
   484  							Say(`TIP: You can upgrade using 'cf upgrade-service %s'\n`, serviceInstanceName),
   485  						))
   486  					})
   487  				})
   488  			})
   489  
   490  			When("bound to apps", func() {
   491  				var (
   492  					appName1     string
   493  					appName2     string
   494  					bindingName1 string
   495  					bindingName2 string
   496  				)
   497  
   498  				BeforeEach(func() {
   499  					appName1 = helpers.PrefixedRandomName("APP1")
   500  					appName2 = helpers.PrefixedRandomName("APP2")
   501  					bindingName1 = helpers.RandomName()
   502  					bindingName2 = helpers.RandomName()
   503  
   504  					broker = servicebrokerstub.New().WithAsyncDelay(time.Millisecond).EnableServiceAccess()
   505  
   506  					helpers.CreateManagedServiceInstance(
   507  						broker.FirstServiceOfferingName(),
   508  						broker.FirstServicePlanName(),
   509  						serviceInstanceName,
   510  					)
   511  
   512  					helpers.WithHelloWorldApp(func(appDir string) {
   513  						Eventually(helpers.CF("push", appName1, "--no-start", "-p", appDir, "-b", "staticfile_buildpack", "--no-route")).Should(Exit(0))
   514  						Eventually(helpers.CF("push", appName2, "--no-start", "-p", appDir, "-b", "staticfile_buildpack", "--no-route")).Should(Exit(0))
   515  					})
   516  
   517  					Eventually(helpers.CF("bind-service", appName1, serviceInstanceName, "--binding-name", bindingName1, "--wait")).Should(Exit(0))
   518  					Eventually(helpers.CF("bind-service", appName2, serviceInstanceName, "--binding-name", bindingName2, "--wait")).Should(Exit(0))
   519  				})
   520  
   521  				It("displays the bound apps", func() {
   522  					session := helpers.CF(serviceCommand, serviceInstanceName, "-v")
   523  					Eventually(session).Should(Exit(0))
   524  
   525  					Expect(session).To(SatisfyAll(
   526  						Say(`Showing bound apps:\n`),
   527  						Say(`name\s+binding name\s+status\s+message\n`),
   528  						Say(`%s\s+%s\s+create succeeded\s+very happy service\n`, appName1, bindingName1),
   529  						Say(`%s\s+%s\s+create succeeded\s+very happy service\n`, appName2, bindingName2),
   530  					))
   531  				})
   532  			})
   533  
   534  			When("--params is requested", func() {
   535  				var key string
   536  				var value string
   537  
   538  				BeforeEach(func() {
   539  					key = "foo"
   540  					value = helpers.RandomName()
   541  
   542  					broker = servicebrokerstub.New().EnableServiceAccess()
   543  					helpers.CreateManagedServiceInstance(
   544  						broker.FirstServiceOfferingName(),
   545  						broker.FirstServicePlanName(),
   546  						serviceInstanceName,
   547  						"-c", fmt.Sprintf(`{"%s":"%s"}`, key, value),
   548  					)
   549  				})
   550  
   551  				It("reports the service instance parameters JSON", func() {
   552  					session := helpers.CF(serviceCommand, serviceInstanceName, "--params")
   553  					Eventually(session).Should(Exit(0))
   554  
   555  					Expect(session).To(SatisfyAll(
   556  						Say(`\{\n`),
   557  						Say(`  %q: %q\n`, key, value),
   558  						Say(`\}\n`),
   559  					))
   560  				})
   561  			})
   562  		})
   563  	})
   564  })