github.com/wanddynosios/cli/v8@v8.7.9-0.20240221182337-1a92e3a7017f/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  
   177  					session := helpers.CF(serviceCommand, serviceInstanceName, "-v")
   178  					Eventually(session).Should(Exit(0))
   179  
   180  					//Delay to reduce flakiness
   181  					time.Sleep(10 * time.Second)
   182  
   183  					Expect(session).To(SatisfyAll(
   184  						Say(`Showing bound apps:\n`),
   185  						Say(`name\s+binding name\s+status\s+message\n`),
   186  						Say(`%s\s+%s\s+create succeeded\s*\n`, appName1, bindingName1),
   187  						Say(`%s\s+%s\s+create succeeded\s*\n`, appName2, bindingName2),
   188  					))
   189  				})
   190  			})
   191  
   192  			When("--params is requested", func() {
   193  				When("service instance parameters have been set", func() {
   194  					It("reports the service instance parameters JSON", func() {
   195  						session := helpers.CF(serviceCommand, serviceInstanceName, "--params")
   196  						Eventually(session).Should(Exit(1))
   197  
   198  						Eventually(session.Err).Should(Say("This service does not support fetching service instance parameters."))
   199  					})
   200  				})
   201  			})
   202  
   203  		})
   204  
   205  		When("the service instance is managed by a broker", func() {
   206  			const (
   207  				testPollingInterval = time.Second
   208  				testTimeout         = time.Minute
   209  			)
   210  
   211  			var broker *servicebrokerstub.ServiceBrokerStub
   212  
   213  			AfterEach(func() {
   214  				broker.Forget()
   215  			})
   216  
   217  			When("created successfully", func() {
   218  				const tags = "foo, bar"
   219  
   220  				BeforeEach(func() {
   221  					broker = servicebrokerstub.New().WithAsyncDelay(time.Nanosecond).EnableServiceAccess()
   222  
   223  					helpers.CreateManagedServiceInstance(
   224  						broker.FirstServiceOfferingName(),
   225  						broker.FirstServicePlanName(),
   226  						serviceInstanceName,
   227  						"-t", tags,
   228  					)
   229  				})
   230  
   231  				It("can show the service instance details", func() {
   232  					session := helpers.CF(serviceCommand, serviceInstanceName)
   233  					Eventually(session).Should(Exit(0))
   234  
   235  					username, _ := helpers.GetCredentials()
   236  					Expect(session).To(SatisfyAll(
   237  						Say(`Showing info of service %s in org %s / space %s as %s...\n`, serviceInstanceName, orgName, spaceName, username),
   238  						Say(`\n`),
   239  						Say(`name:\s+%s\n`, serviceInstanceName),
   240  						Say(`guid:\s+\S+\n`),
   241  						Say(`type:\s+managed`),
   242  						Say(`broker:\s+%s`, broker.Name),
   243  						Say(`offering:\s+%s`, broker.FirstServiceOfferingName()),
   244  						Say(`plan:\s+%s`, broker.FirstServicePlanName()),
   245  						Say(`tags:\s+%s\n`, tags),
   246  						Say(`offering tags:\s+%s\n`, strings.Join(broker.Services[0].Tags, ", ")),
   247  						Say(`description:\s+%s\n`, broker.Services[0].Description),
   248  						Say(`documentation:\s+%s\n`, broker.Services[0].DocumentationURL),
   249  						Say(`dashboard url:\s+http://example.com\n`),
   250  						Say(`\n`),
   251  						Say(`Showing status of last operation:\n`),
   252  						Say(`status:\s+create succeeded\n`),
   253  						Say(`message:\s+very happy service\n`),
   254  						Say(`started:\s+%s\n`, helpers.TimestampRegex),
   255  						Say(`updated:\s+%s\n`, helpers.TimestampRegex),
   256  						Say(`\n`),
   257  						Say(`Showing bound apps:\n`),
   258  						Say(`There are no bound apps for this service instance\.\n`),
   259  						Say(`\n`),
   260  						Say(`Showing sharing info:\n`),
   261  						Say(`This service instance is not currently being shared.`),
   262  						Say(`\n`),
   263  						Say(`Upgrades are not supported by this broker.\n`),
   264  					))
   265  				})
   266  			})
   267  
   268  			When("creation is in progress", func() {
   269  				const (
   270  					tags             = "foo, bar"
   271  					brokerAsyncDelay = time.Second
   272  				)
   273  
   274  				BeforeEach(func() {
   275  					broker = servicebrokerstub.New().WithAsyncDelay(brokerAsyncDelay).EnableServiceAccess()
   276  					command := []string{
   277  						"create-service",
   278  						broker.FirstServiceOfferingName(),
   279  						broker.FirstServicePlanName(),
   280  						serviceInstanceName,
   281  						"-t", tags,
   282  					}
   283  					Eventually(helpers.CF(command...)).Should(Exit(0))
   284  				})
   285  
   286  				It("can show the GUID immediately", func() {
   287  					session := helpers.CF(serviceCommand, serviceInstanceName, "--guid")
   288  					Eventually(session).Should(Exit(0))
   289  					Expect(strings.TrimSpace(string(session.Out.Contents()))).To(HaveLen(36), "GUID wrong length")
   290  				})
   291  
   292  				It("can show the service instance details", func() {
   293  					session := helpers.CF(serviceCommand, serviceInstanceName)
   294  					Eventually(session).Should(Exit(0))
   295  
   296  					username, _ := helpers.GetCredentials()
   297  					Expect(session).To(SatisfyAll(
   298  						Say(`Showing info of service %s in org %s / space %s as %s...\n`, serviceInstanceName, orgName, spaceName, username),
   299  						Say(`\n`),
   300  						Say(`name:\s+%s\n`, serviceInstanceName),
   301  						Say(`guid:\s+\S+\n`),
   302  						Say(`type:\s+managed`),
   303  						Say(`broker:\s+%s`, broker.Name),
   304  						Say(`offering:\s+%s`, broker.FirstServiceOfferingName()),
   305  						Say(`plan:\s+%s`, broker.FirstServicePlanName()),
   306  						Say(`tags:\s+%s\n`, tags),
   307  						Say(`offering tags:\s+%s\n`, strings.Join(broker.Services[0].Tags, ", ")),
   308  						Say(`description:\s+%s\n`, broker.Services[0].Description),
   309  						Say(`documentation:\s+%s\n`, broker.Services[0].DocumentationURL),
   310  						Say(`dashboard url:\s+http://example.com\n`),
   311  						Say(`\n`),
   312  						Say(`Showing status of last operation:\n`),
   313  						Say(`status:\s+create in progress\n`),
   314  						Say(`message:\s+very happy service\n`),
   315  						Say(`started:\s+%s\n`, helpers.TimestampRegex),
   316  						Say(`updated:\s+%s\n`, helpers.TimestampRegex),
   317  						Say(`\n`),
   318  						Say(`Showing bound apps:\n`),
   319  						Say(`There are no bound apps for this service instance\.\n`),
   320  						Say(`\n`),
   321  						Say(`Showing sharing info:\n`),
   322  						Say(`This service instance is not currently being shared.`),
   323  						Say(`\n`),
   324  						Say(`Showing upgrade status:\n`),
   325  						Say(`Upgrades are not supported by this broker.\n`),
   326  					))
   327  				})
   328  			})
   329  
   330  			When("the instance is shared with another space", func() {
   331  				var sharedToSpaceName string
   332  
   333  				BeforeEach(func() {
   334  					sharedToSpaceName = helpers.NewSpaceName()
   335  					helpers.CreateSpace(sharedToSpaceName)
   336  
   337  					broker = servicebrokerstub.New().EnableServiceAccess()
   338  					command := []string{
   339  						"create-service",
   340  						broker.FirstServiceOfferingName(),
   341  						broker.FirstServicePlanName(),
   342  						serviceInstanceName,
   343  					}
   344  					Eventually(helpers.CF(command...)).Should(Exit(0))
   345  
   346  					output := func() *Buffer {
   347  						session := helpers.CF(serviceCommand, serviceInstanceName)
   348  						session.Wait()
   349  						return session.Out
   350  					}
   351  
   352  					Eventually(output, testTimeout, testPollingInterval).Should(Say(`status:\s+create succeeded\n`))
   353  
   354  					command = []string{
   355  						"share-service",
   356  						serviceInstanceName,
   357  						"-s",
   358  						sharedToSpaceName,
   359  					}
   360  					Eventually(helpers.CF(command...)).Should(Exit(0))
   361  				})
   362  
   363  				AfterEach(func() {
   364  					command := []string{
   365  						"unshare-service",
   366  						serviceInstanceName,
   367  						"-s", sharedToSpaceName,
   368  						"-f",
   369  					}
   370  					Eventually(helpers.CF(command...)).Should(Exit(0))
   371  
   372  					helpers.QuickDeleteSpace(sharedToSpaceName)
   373  				})
   374  
   375  				It("can show that the service is being shared", func() {
   376  					session := helpers.CF(serviceCommand, serviceInstanceName)
   377  					Eventually(session).Should(Exit(0))
   378  
   379  					Expect(session).To(SatisfyAll(
   380  						Say(`Showing sharing info:\n`),
   381  						Say(`Shared with spaces:\n`),
   382  						Say(`org\s+space\s+bindings\n`),
   383  						Say(`%s\s+%s\s+0\s*\n`, orgName, sharedToSpaceName),
   384  					))
   385  				})
   386  			})
   387  
   388  			When("the instance is being accessed form shared to space", func() {
   389  				var sharedToSpaceName string
   390  
   391  				BeforeEach(func() {
   392  					sharedToSpaceName = helpers.NewSpaceName()
   393  					helpers.CreateSpace(sharedToSpaceName)
   394  
   395  					broker = servicebrokerstub.New().EnableServiceAccess()
   396  					command := []string{
   397  						"create-service",
   398  						broker.FirstServiceOfferingName(),
   399  						broker.FirstServicePlanName(),
   400  						serviceInstanceName,
   401  					}
   402  					Eventually(helpers.CF(command...)).Should(Exit(0))
   403  
   404  					output := func() *Buffer {
   405  						session := helpers.CF(serviceCommand, serviceInstanceName)
   406  						session.Wait()
   407  						return session.Out
   408  					}
   409  
   410  					Eventually(output, testTimeout, testPollingInterval).Should(Say(`status:\s+create succeeded\n`))
   411  
   412  					command = []string{
   413  						"share-service",
   414  						serviceInstanceName,
   415  						"-s",
   416  						sharedToSpaceName,
   417  					}
   418  					Eventually(helpers.CF(command...)).Should(Exit(0))
   419  
   420  					helpers.TargetOrgAndSpace(orgName, sharedToSpaceName)
   421  				})
   422  
   423  				AfterEach(func() {
   424  					helpers.TargetOrgAndSpace(orgName, spaceName)
   425  
   426  					command := []string{
   427  						"unshare-service",
   428  						serviceInstanceName,
   429  						"-s", sharedToSpaceName,
   430  						"-f",
   431  					}
   432  					Eventually(helpers.CF(command...)).Should(Exit(0))
   433  
   434  					helpers.QuickDeleteSpace(sharedToSpaceName)
   435  				})
   436  
   437  				It("can show that the service has been shared", func() {
   438  					session := helpers.CF(serviceCommand, serviceInstanceName)
   439  					Eventually(session).Should(Exit(0))
   440  
   441  					Expect(session).To(SatisfyAll(
   442  						Say(`Showing sharing info:\n`),
   443  						Say(`This service instance is shared from space %s of org %s.\n`, spaceName, orgName),
   444  					))
   445  				})
   446  			})
   447  
   448  			When("the broker supports maintenance info", func() {
   449  				When("the service is up to date", func() {
   450  					var serviceInstanceName string
   451  
   452  					BeforeEach(func() {
   453  						serviceInstanceName = helpers.NewServiceInstanceName()
   454  						broker = servicebrokerstub.New().WithMaintenanceInfo("1.2.3").EnableServiceAccess()
   455  						helpers.CreateManagedServiceInstance(broker.FirstServiceOfferingName(), broker.FirstServicePlanName(), serviceInstanceName)
   456  					})
   457  
   458  					It("says that the service has no upgrades available", func() {
   459  						session := helpers.CF(serviceCommand, serviceInstanceName)
   460  						Eventually(session).Should(Exit(0))
   461  
   462  						Expect(session).To(SatisfyAll(
   463  							Say(`Showing upgrade status:\n`),
   464  							Say(`There is no upgrade available for this service.\n`),
   465  						))
   466  					})
   467  				})
   468  
   469  				When("an update is available", func() {
   470  					var serviceInstanceName string
   471  
   472  					BeforeEach(func() {
   473  						serviceInstanceName = helpers.NewServiceInstanceName()
   474  						broker = servicebrokerstub.New().WithMaintenanceInfo("1.2.3").EnableServiceAccess()
   475  						helpers.CreateManagedServiceInstance(broker.FirstServiceOfferingName(), broker.FirstServicePlanName(), serviceInstanceName)
   476  
   477  						broker.WithMaintenanceInfo("1.2.4", "really cool improvement").Configure().Register()
   478  					})
   479  
   480  					It("displays information about the upgrade", func() {
   481  						session := helpers.CF(serviceCommand, serviceInstanceName)
   482  						Eventually(session).Should(Exit(0))
   483  
   484  						Expect(session).To(SatisfyAll(
   485  							Say(`Showing upgrade status:\n`),
   486  							Say(`There is an upgrade available for this service.\n`),
   487  							Say(`Upgrade description: really cool improvement\n`),
   488  							Say(`TIP: You can upgrade using 'cf upgrade-service %s'\n`, serviceInstanceName),
   489  						))
   490  					})
   491  				})
   492  			})
   493  
   494  			When("bound to apps", func() {
   495  				var (
   496  					appName1     string
   497  					appName2     string
   498  					bindingName1 string
   499  					bindingName2 string
   500  				)
   501  
   502  				BeforeEach(func() {
   503  					appName1 = helpers.PrefixedRandomName("APP1")
   504  					appName2 = helpers.PrefixedRandomName("APP2")
   505  					bindingName1 = helpers.RandomName()
   506  					bindingName2 = helpers.RandomName()
   507  
   508  					broker = servicebrokerstub.New().WithAsyncDelay(time.Millisecond).EnableServiceAccess()
   509  
   510  					helpers.CreateManagedServiceInstance(
   511  						broker.FirstServiceOfferingName(),
   512  						broker.FirstServicePlanName(),
   513  						serviceInstanceName,
   514  					)
   515  
   516  					helpers.WithHelloWorldApp(func(appDir string) {
   517  						Eventually(helpers.CF("push", appName1, "--no-start", "-p", appDir, "-b", "staticfile_buildpack", "--no-route")).Should(Exit(0))
   518  						Eventually(helpers.CF("push", appName2, "--no-start", "-p", appDir, "-b", "staticfile_buildpack", "--no-route")).Should(Exit(0))
   519  					})
   520  
   521  					Eventually(helpers.CF("bind-service", appName1, serviceInstanceName, "--binding-name", bindingName1, "--wait")).Should(Exit(0))
   522  					Eventually(helpers.CF("bind-service", appName2, serviceInstanceName, "--binding-name", bindingName2, "--wait")).Should(Exit(0))
   523  				})
   524  
   525  				It("displays the bound apps", func() {
   526  					session := helpers.CF(serviceCommand, serviceInstanceName, "-v")
   527  					Eventually(session).Should(Exit(0))
   528  
   529  					Expect(session).To(SatisfyAll(
   530  						Say(`Showing bound apps:\n`),
   531  						Say(`name\s+binding name\s+status\s+message\n`),
   532  						Say(`%s\s+%s\s+create succeeded\s+very happy service\n`, appName1, bindingName1),
   533  						Say(`%s\s+%s\s+create succeeded\s+very happy service\n`, appName2, bindingName2),
   534  					))
   535  				})
   536  			})
   537  
   538  			When("--params is requested", func() {
   539  				var key string
   540  				var value string
   541  
   542  				BeforeEach(func() {
   543  					key = "foo"
   544  					value = helpers.RandomName()
   545  
   546  					broker = servicebrokerstub.New().EnableServiceAccess()
   547  					helpers.CreateManagedServiceInstance(
   548  						broker.FirstServiceOfferingName(),
   549  						broker.FirstServicePlanName(),
   550  						serviceInstanceName,
   551  						"-c", fmt.Sprintf(`{"%s":"%s"}`, key, value),
   552  					)
   553  				})
   554  
   555  				It("reports the service instance parameters JSON", func() {
   556  					session := helpers.CF(serviceCommand, serviceInstanceName, "--params")
   557  					Eventually(session).Should(Exit(0))
   558  
   559  					Expect(session).To(SatisfyAll(
   560  						Say(`\{\n`),
   561  						Say(`  %q: %q\n`, key, value),
   562  						Say(`\}\n`),
   563  					))
   564  				})
   565  			})
   566  		})
   567  	})
   568  })