github.com/LukasHeimann/cloudfoundrycli/v8@v8.4.4/integration/v7/isolated/service_command_test.go (about)

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