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

     1  package isolated
     2  
     3  import (
     4  	"fmt"
     5  	"regexp"
     6  
     7  	"github.com/LukasHeimann/cloudfoundrycli/v8/integration/helpers/servicebrokerstub"
     8  
     9  	. "github.com/LukasHeimann/cloudfoundrycli/v8/cf/util/testhelpers/matchers"
    10  	"github.com/LukasHeimann/cloudfoundrycli/v8/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("set-label command", func() {
    18  	Describe("help", func() {
    19  		When("--help flag is set", func() {
    20  			It("appears in cf help -a", func() {
    21  				session := helpers.CF("help", "-a")
    22  				Eventually(session).Should(Exit(0))
    23  				Expect(session).To(HaveCommandInCategoryWithDescription("set-label", "METADATA", "Set a label (key-value pairs) for an API resource"))
    24  			})
    25  
    26  			It("Displays command usage to output", func() {
    27  				session := helpers.CF("set-label", "--help")
    28  
    29  				Eventually(session).Should(Say("NAME:"))
    30  				Eventually(session).Should(Say(`\s+set-label - Set a label \(key-value pairs\) for an API resource`))
    31  				Eventually(session).Should(Say("USAGE:"))
    32  				Eventually(session).Should(Say(`\s+cf set-label RESOURCE RESOURCE_NAME KEY=VALUE\.\.\.`))
    33  				Eventually(session).Should(Say("EXAMPLES:"))
    34  				Eventually(session).Should(Say(`\s+cf set-label app dora env=production`))
    35  				Eventually(session).Should(Say(`\s+cf set-label org business pci=true public-facing=false`))
    36  				Eventually(session).Should(Say(`\s+cf set-label buildpack go_buildpack go=1.12 -s cflinuxfs3`))
    37  				Eventually(session).Should(Say("RESOURCES:"))
    38  				Eventually(session).Should(Say(`\s+app`))
    39  				Eventually(session).Should(Say(`\s+buildpack`))
    40  				Eventually(session).Should(Say(`\s+domain`))
    41  				Eventually(session).Should(Say(`\s+org`))
    42  				Eventually(session).Should(Say(`\s+route`))
    43  				Eventually(session).Should(Say(`\s+service-broker`))
    44  				Eventually(session).Should(Say(`\s+service-instance`))
    45  				Eventually(session).Should(Say(`\s+service-offering`))
    46  				Eventually(session).Should(Say(`\s+service-plan`))
    47  				Eventually(session).Should(Say(`\s+space`))
    48  				Eventually(session).Should(Say(`\s+stack`))
    49  				Eventually(session).Should(Say("OPTIONS:"))
    50  				Eventually(session).Should(Say(`\s+--stack, -s\s+Specify stack to disambiguate buildpacks with the same name`))
    51  				Eventually(session).Should(Say(`\s+--broker, -b\s+Specify a service broker to disambiguate service offerings or service plans with the same name`))
    52  				Eventually(session).Should(Say(`\s+--offering, -e\s+Specify a service offering to disambiguate service plans with the same name`))
    53  				Eventually(session).Should(Say("SEE ALSO:"))
    54  				Eventually(session).Should(Say(`\s+labels, unset-label`))
    55  
    56  				Eventually(session).Should(Exit(0))
    57  			})
    58  		})
    59  	})
    60  
    61  	When("the environment is set up correctly", func() {
    62  		var (
    63  			orgName       string
    64  			spaceName     string
    65  			username      string
    66  			stackNameBase string
    67  		)
    68  
    69  		testExpectedBehaviors := func(resourceType, resourceTypeFormatted, resourceName string) {
    70  			By("checking the behavior when the resource does not exist", func() {
    71  				unknownResourceName := "non-existent-" + resourceType
    72  				session := helpers.CF("set-label", resourceType, unknownResourceName, "some-key=some-value")
    73  				Eventually(session.Err).Should(Say("%s '%s' not found", resourceTypeFormatted, unknownResourceName))
    74  				Eventually(session).Should(Say("FAILED"))
    75  				Eventually(session).Should(Exit(1))
    76  			})
    77  
    78  			By("checking the behavior when the label has an empty key and an invalid value", func() {
    79  				session := helpers.CF("set-label", resourceType, resourceName, "=test", "sha2=108&eb90d734")
    80  				Eventually(session.Err).Should(Say("Metadata label key error: key cannot be empty string, Metadata label value error: '108&eb90d734' contains invalid characters"))
    81  				Eventually(session).Should(Say("FAILED"))
    82  				Eventually(session).Should(Exit(1))
    83  			})
    84  
    85  			By("checking the behavior when the label does not include a '=' to separate the key and value", func() {
    86  				session := helpers.CF("set-label", resourceType, resourceName, "test-label")
    87  				Eventually(session.Err).Should(Say("Metadata error: no value provided for label 'test-label'"))
    88  				Eventually(session).Should(Say("FAILED"))
    89  				Eventually(session).Should(Exit(1))
    90  			})
    91  		}
    92  
    93  		BeforeEach(func() {
    94  			username, _ = helpers.GetCredentials()
    95  			orgName = helpers.NewOrgName()
    96  			stackNameBase = helpers.NewStackName()
    97  		})
    98  
    99  		When("assigning label to app", func() {
   100  			var appName string
   101  
   102  			BeforeEach(func() {
   103  				spaceName = helpers.NewSpaceName()
   104  				appName = helpers.PrefixedRandomName("app")
   105  
   106  				helpers.SetupCF(orgName, spaceName)
   107  				helpers.WithHelloWorldApp(func(appDir string) {
   108  					Eventually(helpers.CF("push", appName, "-p", appDir, "--no-start")).Should(Exit(0))
   109  				})
   110  			})
   111  
   112  			AfterEach(func() {
   113  				helpers.QuickDeleteOrg(orgName)
   114  			})
   115  
   116  			It("has the expected shared behaviors", func() {
   117  				testExpectedBehaviors("app", "App", appName)
   118  			})
   119  
   120  			It("sets the specified labels on the app", func() {
   121  				session := helpers.CF("set-label", "app", appName, "some-key=some-value", "some-other-key=some-other-value")
   122  				Eventually(session).Should(Say(regexp.QuoteMeta(`Setting label(s) for app %s in org %s / space %s as %s...`), appName, orgName, spaceName, username))
   123  				Eventually(session).Should(Say("OK"))
   124  				Eventually(session).Should(Exit(0))
   125  
   126  				helpers.CheckExpectedLabels(fmt.Sprintf("/v3/apps/%s", helpers.AppGUID(appName)), false, helpers.MetadataLabels{
   127  					"some-key":       "some-value",
   128  					"some-other-key": "some-other-value",
   129  				})
   130  			})
   131  
   132  			When("more than one value is provided for the same key", func() {
   133  				It("uses the last value", func() {
   134  					session := helpers.CF("set-label", "app", appName, "owner=sue", "owner=beth")
   135  					Eventually(session).Should(Exit(0))
   136  
   137  					helpers.CheckExpectedLabels(fmt.Sprintf("/v3/apps/%s", helpers.AppGUID(appName)), false, helpers.MetadataLabels{
   138  						"owner": "beth",
   139  					})
   140  				})
   141  			})
   142  		})
   143  
   144  		When("assigning label to domain", func() {
   145  			var (
   146  				domainName string
   147  				domain     helpers.Domain
   148  			)
   149  
   150  			BeforeEach(func() {
   151  				domainName = helpers.NewDomainName("labels")
   152  				domain = helpers.NewDomain(orgName, domainName)
   153  
   154  				helpers.SetupCFWithOrgOnly(orgName)
   155  				domain.CreatePrivate()
   156  			})
   157  
   158  			AfterEach(func() {
   159  				domain.DeletePrivate()
   160  				helpers.QuickDeleteOrg(orgName)
   161  			})
   162  
   163  			It("has the expected shared behaviors", func() {
   164  				testExpectedBehaviors("domain", "Domain", domainName)
   165  			})
   166  
   167  			It("sets the specified labels on the domain", func() {
   168  				session := helpers.CF("set-label", "domain", domainName, "some-key=some-value", "some-other-key=some-other-value")
   169  				Eventually(session).Should(Exit(0))
   170  				Expect(session).Should(Say(regexp.QuoteMeta(`Setting label(s) for domain %s as %s...`), domainName, username))
   171  				Expect(session).Should(Say("OK"))
   172  
   173  				helpers.CheckExpectedLabels(fmt.Sprintf("/v3/domains?names=%s", domainName), true, helpers.MetadataLabels{
   174  					"some-key":       "some-value",
   175  					"some-other-key": "some-other-value",
   176  				})
   177  			})
   178  
   179  			When("more than one value is provided for the same key", func() {
   180  				It("uses the last value", func() {
   181  					session := helpers.CF("set-label", "domain", domainName, "some-key=some-value", "some-key=some-other-value")
   182  					Eventually(session).Should(Exit(0))
   183  					Expect(session).Should(Say(regexp.QuoteMeta(`Setting label(s) for domain %s as %s...`), domainName, username))
   184  					Expect(session).Should(Say("OK"))
   185  
   186  					helpers.CheckExpectedLabels(fmt.Sprintf("/v3/domains?names=%s", domainName), true, helpers.MetadataLabels{
   187  						"some-key": "some-other-value",
   188  					})
   189  				})
   190  			})
   191  		})
   192  
   193  		When("assigning label to space", func() {
   194  			BeforeEach(func() {
   195  				spaceName = helpers.NewSpaceName()
   196  				helpers.SetupCF(orgName, spaceName)
   197  			})
   198  
   199  			AfterEach(func() {
   200  				helpers.QuickDeleteOrg(orgName)
   201  			})
   202  
   203  			It("has the expected shared behaviors", func() {
   204  				testExpectedBehaviors("space", "Space", spaceName)
   205  			})
   206  
   207  			It("sets the specified labels on the space", func() {
   208  				session := helpers.CF("set-label", "space", spaceName, "some-key=some-value", "some-other-key=some-other-value")
   209  				Eventually(session).Should(Say(regexp.QuoteMeta(`Setting label(s) for space %s in org %s as %s...`), spaceName, orgName, username))
   210  				Eventually(session).Should(Say("OK"))
   211  				Eventually(session).Should(Exit(0))
   212  
   213  				helpers.CheckExpectedLabels(fmt.Sprintf("/v3/spaces/%s", helpers.GetSpaceGUID(spaceName)), false, helpers.MetadataLabels{
   214  					"some-key":       "some-value",
   215  					"some-other-key": "some-other-value",
   216  				})
   217  			})
   218  
   219  			When("more than one value is provided for the same key", func() {
   220  				It("uses the last value", func() {
   221  					session := helpers.CF("set-label", "space", spaceName, "owner=sue", "owner=beth")
   222  					Eventually(session).Should(Exit(0))
   223  
   224  					helpers.CheckExpectedLabels(fmt.Sprintf("/v3/spaces/%s", helpers.GetSpaceGUID(spaceName)), false, helpers.MetadataLabels{
   225  						"owner": "beth",
   226  					})
   227  				})
   228  			})
   229  		})
   230  
   231  		When("assigning label to org", func() {
   232  			BeforeEach(func() {
   233  				helpers.SetupCFWithOrgOnly(orgName)
   234  			})
   235  
   236  			AfterEach(func() {
   237  				helpers.QuickDeleteOrg(orgName)
   238  			})
   239  
   240  			It("has the expected shared behaviors", func() {
   241  				testExpectedBehaviors("org", "Organization", orgName)
   242  			})
   243  
   244  			It("sets the specified labels on the org", func() {
   245  				session := helpers.CF("set-label", "org", orgName, "pci=true", "public-facing=false")
   246  				Eventually(session).Should(Say(regexp.QuoteMeta(`Setting label(s) for org %s as %s...`), orgName, username))
   247  				Eventually(session).Should(Say("OK"))
   248  				Eventually(session).Should(Exit(0))
   249  
   250  				helpers.CheckExpectedLabels(fmt.Sprintf("/v3/organizations/%s", helpers.GetOrgGUID(orgName)), false, helpers.MetadataLabels{
   251  					"pci":           "true",
   252  					"public-facing": "false",
   253  				})
   254  			})
   255  
   256  			When("more than one value is provided for the same key", func() {
   257  				It("uses the last value", func() {
   258  					session := helpers.CF("set-label", "org", orgName, "owner=sue", "owner=beth")
   259  					Eventually(session).Should(Exit(0))
   260  
   261  					helpers.CheckExpectedLabels(fmt.Sprintf("/v3/organizations/%s", helpers.GetOrgGUID(orgName)), false, helpers.MetadataLabels{
   262  						"owner": "beth",
   263  					})
   264  				})
   265  			})
   266  		})
   267  
   268  		When("assigning label to route", func() {
   269  			var (
   270  				orgGUID    string
   271  				routeName  string
   272  				domainName string
   273  				domain     helpers.Domain
   274  			)
   275  			BeforeEach(func() {
   276  				orgName = helpers.NewOrgName()
   277  				spaceName = helpers.NewSpaceName()
   278  				helpers.SetupCF(orgName, spaceName)
   279  
   280  				orgGUID = helpers.GetOrgGUID(orgName)
   281  				domainName = helpers.NewDomainName()
   282  				domain = helpers.NewDomain(orgName, domainName)
   283  				domain.Create()
   284  				Eventually(helpers.CF("create-route", domainName)).Should(Exit(0))
   285  				routeName = domainName
   286  			})
   287  
   288  			AfterEach(func() {
   289  				Eventually(helpers.CF("delete-route", domainName, "-f")).Should(Exit(0))
   290  				domain.Delete()
   291  				helpers.QuickDeleteOrg(orgName)
   292  			})
   293  
   294  			It("has the expected shared behaviors", func() {
   295  				// The Domain is checked first, hence why the error message says 'Domain' and not 'Route'
   296  				testExpectedBehaviors("route", "Domain", routeName)
   297  			})
   298  
   299  			When("the route contains a port", func() {
   300  				var tcpDomain helpers.Domain
   301  
   302  				BeforeEach(func() {
   303  					tcpDomainName := helpers.NewDomainName()
   304  					tcpDomain = helpers.NewDomain(orgName, tcpDomainName)
   305  					tcpDomain.CreateWithRouterGroup(helpers.FindOrCreateTCPRouterGroup(0))
   306  
   307  					Eventually(helpers.CF("create-route", tcpDomainName, "--port", "1028")).Should(Exit(0))
   308  					Eventually(helpers.CF("create-route", tcpDomainName, "--port", "1029")).Should(Exit(0))
   309  					routeName = tcpDomainName + ":1028"
   310  				})
   311  
   312  				AfterEach(func() {
   313  					tcpDomain.DeleteShared()
   314  				})
   315  
   316  				It("sets the specified labels on the route", func() {
   317  					session := helpers.CF("set-label", "route", routeName, "some-key=some-value", "some-other-key=some-other-value")
   318  
   319  					Eventually(session).Should(Say(regexp.QuoteMeta(`Setting label(s) for route %s in org %s / space %s as %s...`), routeName, orgName, spaceName, username))
   320  					Eventually(session).Should(Say("OK"))
   321  					Eventually(session).Should(Exit(0))
   322  
   323  					helpers.CheckExpectedLabels("/v3/routes?ports=1028", true, helpers.MetadataLabels{
   324  						"some-key":       "some-value",
   325  						"some-other-key": "some-other-value",
   326  					})
   327  
   328  					helpers.CheckExpectedLabels("/v3/routes?ports=1029", true, helpers.MetadataLabels{})
   329  				})
   330  			})
   331  
   332  			When("the route is unknown", func() {
   333  				It("displays an error", func() {
   334  					invalidRoute := "non-existent-host." + domainName
   335  					session := helpers.CF("set-label", "route", invalidRoute, "some-key=some-value")
   336  					Eventually(session.Err).Should(Say(`Route with host 'non-existent-host', domain '%s', and path '/' not found\.`, domainName))
   337  					Eventually(session.Out).Should(Say("FAILED"))
   338  					Eventually(session).Should(Exit(1))
   339  				})
   340  			})
   341  
   342  			It("sets the specified labels on the route", func() {
   343  				session := helpers.CF("set-label", "route", routeName, "some-key=some-value", "some-other-key=some-other-value")
   344  
   345  				Eventually(session).Should(Say(regexp.QuoteMeta(`Setting label(s) for route %s in org %s / space %s as %s...`), routeName, orgName, spaceName, username))
   346  				Eventually(session).Should(Say("OK"))
   347  				Eventually(session).Should(Exit(0))
   348  
   349  				helpers.CheckExpectedLabels(fmt.Sprintf("/v3/routes?organization_guids=%s", orgGUID), true, helpers.MetadataLabels{
   350  					"some-key":       "some-value",
   351  					"some-other-key": "some-other-value",
   352  				})
   353  			})
   354  
   355  			When("more than one value is provided for the same key", func() {
   356  				It("uses the last value", func() {
   357  					session := helpers.CF("set-label", "route", routeName, "owner=sue", "owner=beth")
   358  					Eventually(session).Should(Exit(0))
   359  
   360  					helpers.CheckExpectedLabels(fmt.Sprintf("/v3/routes?organization_guids=%s", orgGUID), true, helpers.MetadataLabels{
   361  						"owner": "beth",
   362  					})
   363  				})
   364  			})
   365  		})
   366  
   367  		When("assigning label to buildpack", func() {
   368  			var (
   369  				buildpackName string
   370  			)
   371  
   372  			BeforeEach(func() {
   373  				helpers.LoginCF()
   374  				buildpackName = helpers.NewBuildpackName()
   375  			})
   376  
   377  			When("the buildpack exists for at most one stack", func() {
   378  				var (
   379  					currentStack string
   380  				)
   381  
   382  				BeforeEach(func() {
   383  					currentStack = helpers.PreferredStack()
   384  					helpers.BuildpackWithStack(func(buildpackPath string) {
   385  						session := helpers.CF("create-buildpack", buildpackName, buildpackPath, "98")
   386  						Eventually(session).Should(Exit(0))
   387  					}, currentStack)
   388  				})
   389  
   390  				AfterEach(func() {
   391  					helpers.CF("delete-buildpack", buildpackName, "-f", "-s", currentStack)
   392  				})
   393  
   394  				It("has the expected shared behaviors", func() {
   395  					testExpectedBehaviors("buildpack", "Buildpack", buildpackName)
   396  				})
   397  
   398  				It("sets the specified labels on the buildpack", func() {
   399  					session := helpers.CF("set-label", "buildpack", buildpackName, "pci=true", "public-facing=false")
   400  					Eventually(session).Should(Say(regexp.QuoteMeta(`Setting label(s) for buildpack %s as %s...`), buildpackName, username))
   401  					Eventually(session).Should(Say("OK"))
   402  					Eventually(session).Should(Exit(0))
   403  
   404  					buildpackGUID := helpers.BuildpackGUIDByNameAndStack(buildpackName, currentStack)
   405  					helpers.CheckExpectedLabels(fmt.Sprintf("/v3/buildpacks/%s", buildpackGUID), false, helpers.MetadataLabels{
   406  						"pci":           "true",
   407  						"public-facing": "false",
   408  					})
   409  				})
   410  
   411  				When("the buildpack exists for multiple stacks", func() {
   412  					var stacks []string
   413  
   414  					BeforeEach(func() {
   415  						stacks = []string{helpers.PreferredStack(), helpers.CreateStack()}
   416  
   417  						helpers.BuildpackWithStack(func(buildpackPath string) {
   418  							createSession := helpers.CF("create-buildpack", buildpackName, buildpackPath, "99")
   419  							Eventually(createSession).Should(Exit(0))
   420  						}, stacks[1])
   421  					})
   422  					AfterEach(func() {
   423  						helpers.CF("delete-buildpack", buildpackName, "-f", "-s", stacks[1])
   424  						helpers.DeleteStack(stacks[1])
   425  					})
   426  
   427  					When("stack is not specified", func() {
   428  						It("displays an error", func() {
   429  							session := helpers.CF("set-label", "buildpack", buildpackName, "some-key=some-value")
   430  							Eventually(session.Err).Should(Say(fmt.Sprintf("Multiple buildpacks named %s found. Specify a stack name by using a '-s' flag.", buildpackName)))
   431  							Eventually(session).Should(Say("FAILED"))
   432  							Eventually(session).Should(Exit(1))
   433  						})
   434  					})
   435  
   436  					When("stack is specified", func() {
   437  						It("sets the specified labels on the correct buildpack", func() {
   438  							session := helpers.CF("set-label", "buildpack", buildpackName, "pci=true", "public-facing=false", "--stack", stacks[1])
   439  							Eventually(session).Should(Say(regexp.QuoteMeta(`Setting label(s) for buildpack %s with stack %s as %s...`), buildpackName, stacks[1], username))
   440  							Eventually(session).Should(Say("OK"))
   441  							Eventually(session).Should(Exit(0))
   442  
   443  							buildpackGUID := helpers.BuildpackGUIDByNameAndStack(buildpackName, stacks[1])
   444  							helpers.CheckExpectedLabels(fmt.Sprintf("/v3/buildpacks/%s", buildpackGUID), false, helpers.MetadataLabels{
   445  								"pci":           "true",
   446  								"public-facing": "false",
   447  							})
   448  						})
   449  					})
   450  				})
   451  
   452  				When("the buildpack exists in general but does NOT exist for the specified stack", func() {
   453  					It("displays an error", func() {
   454  						session := helpers.CF("set-label", "buildpack", buildpackName, "some-key=some-value", "--stack", "FAKE")
   455  						Eventually(session.Err).Should(Say(fmt.Sprintf("Buildpack '%s' with stack 'FAKE' not found", buildpackName)))
   456  						Eventually(session).Should(Say("FAILED"))
   457  						Eventually(session).Should(Exit(1))
   458  					})
   459  				})
   460  
   461  				When("more than one value is provided for the same key", func() {
   462  					It("uses the last value", func() {
   463  						session := helpers.CF("set-label", "buildpack", buildpackName, "owner=sue", "owner=beth")
   464  						Eventually(session).Should(Exit(0))
   465  
   466  						buildpackGUID := helpers.BuildpackGUIDByNameAndStack(buildpackName, currentStack)
   467  						helpers.CheckExpectedLabels(fmt.Sprintf("/v3/buildpacks/%s", buildpackGUID), false, helpers.MetadataLabels{
   468  							"owner": "beth",
   469  						})
   470  					})
   471  				})
   472  			})
   473  
   474  			When("the buildpack exists for multiple stacks", func() {
   475  				var (
   476  					stacks             [3]string
   477  					buildpackGUIDs     [3]string
   478  					testWithStackCount int
   479  				)
   480  
   481  				BeforeEach(func() {
   482  					stacks[0] = helpers.PreferredStack()
   483  					testWithStackCount += 1
   484  					stacks[1] = helpers.CreateStack(fmt.Sprintf("%s-%d", stackNameBase, testWithStackCount))
   485  
   486  					for i := 0; i < 2; i++ {
   487  						helpers.BuildpackWithStack(func(buildpackPath string) {
   488  							createSession := helpers.CF("create-buildpack", buildpackName, buildpackPath,
   489  								fmt.Sprintf("%d", 95+i))
   490  							Eventually(createSession).Should(Exit(0))
   491  							buildpackGUIDs[i] = helpers.BuildpackGUIDByNameAndStack(buildpackName, stacks[i])
   492  						}, stacks[i])
   493  					}
   494  					helpers.CF("curl", "/v3/buildpacks?names="+buildpackName)
   495  				})
   496  
   497  				AfterEach(func() {
   498  					helpers.CF("delete-buildpack", buildpackName, "-f", "-s", stacks[0])
   499  					helpers.CF("delete-buildpack", buildpackName, "-f", "-s", stacks[1])
   500  					helpers.DeleteStack(stacks[1])
   501  				})
   502  
   503  				When("all buildpacks are stack-scoped", func() {
   504  					When("no stack is specified", func() {
   505  						It("displays an error", func() {
   506  							session := helpers.CF("set-label", "buildpack", buildpackName, "some-key=some-value")
   507  							Eventually(session.Err).Should(Say(fmt.Sprintf("Multiple buildpacks named %s found. Specify a stack name by using a '-s' flag.", buildpackName)))
   508  							Eventually(session).Should(Say("FAILED"))
   509  							Eventually(session).Should(Exit(1))
   510  						})
   511  					})
   512  
   513  					When("a non-existent stack is specified", func() {
   514  						It("displays an error", func() {
   515  							bogusStackName := stacks[0] + "-bogus-" + stacks[1]
   516  							session := helpers.CF("set-label", "buildpack", buildpackName, "olive=3", "mangosteen=4", "--stack", bogusStackName)
   517  							Eventually(session.Err).Should(Say(regexp.QuoteMeta(fmt.Sprintf("Buildpack '%s' with stack '%s' not found", buildpackName, bogusStackName))))
   518  							Eventually(session).Should(Say("FAILED"))
   519  							Eventually(session).Should(Exit(1))
   520  						})
   521  					})
   522  
   523  					When("an existing stack is specified", func() {
   524  						It("updates the correct buildpack", func() {
   525  							session := helpers.CF("set-label", "buildpack", buildpackName, "peach=5", "quince=6", "--stack", stacks[0])
   526  							Eventually(session).Should(Say(regexp.QuoteMeta(`Setting label(s) for buildpack %s with stack %s as %s...`), buildpackName, stacks[0], username))
   527  							Eventually(session).Should(Say("OK"))
   528  							Eventually(session).Should(Exit(0))
   529  
   530  							helpers.CheckExpectedLabels(fmt.Sprintf("/v3/buildpacks/%s", buildpackGUIDs[0]), false, helpers.MetadataLabels{
   531  								"peach":  "5",
   532  								"quince": "6",
   533  							})
   534  						})
   535  					})
   536  				})
   537  
   538  				When("one of the buildpacks is not stack-scoped", func() {
   539  					BeforeEach(func() {
   540  						helpers.BuildpackWithoutStack(func(buildpackPath string) {
   541  							createSession := helpers.CF("create-buildpack", buildpackName, buildpackPath, "97")
   542  							Eventually(createSession).Should(Exit(0))
   543  							buildpackGUIDs[2] = helpers.BuildpackGUIDByNameAndStack(buildpackName, "")
   544  						})
   545  					})
   546  					AfterEach(func() {
   547  						helpers.CF("delete-buildpack", buildpackName, "-f")
   548  					})
   549  
   550  					When("no stack is specified", func() {
   551  						It("updates the unscoped buildpack", func() {
   552  							session := helpers.CF("set-label", "buildpack", buildpackName, "mango=1", "figs=2")
   553  							Eventually(session).Should(Say(regexp.QuoteMeta(`Setting label(s) for buildpack %s as %s...`), buildpackName, username))
   554  							Eventually(session).Should(Say("OK"))
   555  							Eventually(session).Should(Exit(0))
   556  
   557  							helpers.CheckExpectedLabels(fmt.Sprintf("/v3/buildpacks/%s", buildpackGUIDs[2]), false, helpers.MetadataLabels{
   558  								"mango": "1",
   559  								"figs":  "2",
   560  							})
   561  						})
   562  					})
   563  
   564  					When("an existing stack is specified", func() {
   565  						It("updates the correct buildpack", func() {
   566  							session := helpers.CF("set-label", "buildpack", buildpackName, "tangelo=3", "lemon=4", "--stack", stacks[1])
   567  							Eventually(session).Should(Say(regexp.QuoteMeta(`Setting label(s) for buildpack %s with stack %s as %s...`), buildpackName, stacks[1], username))
   568  							Eventually(session).Should(Say("OK"))
   569  							Eventually(session).Should(Exit(0))
   570  
   571  							helpers.CheckExpectedLabels(fmt.Sprintf("/v3/buildpacks/%s", buildpackGUIDs[1]), false, helpers.MetadataLabels{
   572  								"tangelo": "3",
   573  								"lemon":   "4",
   574  							})
   575  						})
   576  					})
   577  
   578  					When("a non-existent stack is specified", func() {
   579  						It("displays an error", func() {
   580  							bogusStackName := stacks[0] + "-bogus-" + stacks[1]
   581  							session := helpers.CF("set-label", "buildpack", buildpackName, "olive=3", "mangosteen=4", "--stack", bogusStackName)
   582  							Eventually(session.Err).Should(Say(regexp.QuoteMeta(fmt.Sprintf("Buildpack '%s' with stack '%s' not found", buildpackName, bogusStackName))))
   583  							Eventually(session).Should(Say("FAILED"))
   584  							Eventually(session).Should(Exit(1))
   585  						})
   586  					})
   587  				})
   588  			})
   589  		})
   590  
   591  		When("assigning label to stack", func() {
   592  			var (
   593  				stackName string
   594  				stackGUID string
   595  			)
   596  
   597  			BeforeEach(func() {
   598  				helpers.LoginCF()
   599  				stackName, stackGUID = helpers.CreateStackWithGUID()
   600  			})
   601  
   602  			AfterEach(func() {
   603  				deleteResourceByGUID(stackGUID, "stacks")
   604  			})
   605  
   606  			It("has the expected shared behaviors", func() {
   607  				testExpectedBehaviors("stack", "Stack", stackName)
   608  			})
   609  
   610  			It("sets the specified labels on the stack", func() {
   611  				session := helpers.CF("set-label", "stack", stackName, "pci=true", "public-facing=false")
   612  				Eventually(session).Should(Say(regexp.QuoteMeta(`Setting label(s) for stack %s as %s...`), stackName, username))
   613  				Eventually(session).Should(Say("OK"))
   614  				Eventually(session).Should(Exit(0))
   615  
   616  				helpers.CheckExpectedLabels(fmt.Sprintf("/v3/stacks/%s", stackGUID), false, helpers.MetadataLabels{
   617  					"pci":           "true",
   618  					"public-facing": "false",
   619  				})
   620  			})
   621  
   622  			When("more than one value is provided for the same key", func() {
   623  				It("uses the last value", func() {
   624  					session := helpers.CF("set-label", "stack", stackName, "owner=sue", "owner=beth")
   625  					Eventually(session).Should(Exit(0))
   626  
   627  					helpers.CheckExpectedLabels(fmt.Sprintf("/v3/stacks/%s", stackGUID), false, helpers.MetadataLabels{
   628  						"owner": "beth",
   629  					})
   630  				})
   631  			})
   632  		})
   633  
   634  		When("assigning label to service-broker", func() {
   635  			var broker *servicebrokerstub.ServiceBrokerStub
   636  
   637  			BeforeEach(func() {
   638  				orgName = helpers.NewOrgName()
   639  				spaceName = helpers.NewSpaceName()
   640  				helpers.SetupCF(orgName, spaceName)
   641  				broker = servicebrokerstub.Register()
   642  			})
   643  
   644  			AfterEach(func() {
   645  				helpers.QuickDeleteOrg(orgName)
   646  				broker.Forget()
   647  			})
   648  
   649  			It("has the expected shared behaviors", func() {
   650  				testExpectedBehaviors("service-broker", "Service broker", broker.Name)
   651  			})
   652  
   653  			It("sets the specified labels on the service-broker", func() {
   654  				session := helpers.CF("set-label", "service-broker", broker.Name, "some-key=some-value", "some-other-key=some-other-value")
   655  				Eventually(session).Should(Say(regexp.QuoteMeta(`Setting label(s) for service-broker %s as %s...`), broker.Name, username))
   656  				Eventually(session).Should(Say("OK"))
   657  				Eventually(session).Should(Exit(0))
   658  
   659  				helpers.CheckExpectedLabels(fmt.Sprintf("/v3/service_brokers?names=%s", broker.Name), true, helpers.MetadataLabels{
   660  					"some-key":       "some-value",
   661  					"some-other-key": "some-other-value",
   662  				})
   663  			})
   664  
   665  			When("more than one value is provided for the same key", func() {
   666  				It("uses the last value", func() {
   667  					session := helpers.CF("set-label", "service-broker", broker.Name, "owner=sue", "owner=beth")
   668  					Eventually(session).Should(Exit(0))
   669  
   670  					helpers.CheckExpectedLabels(fmt.Sprintf("/v3/service_brokers?names=%s", broker.Name), true, helpers.MetadataLabels{
   671  						"owner": "beth",
   672  					})
   673  				})
   674  			})
   675  		})
   676  
   677  		When("assigning label to service-instance", func() {
   678  			var serviceInstanceName string
   679  
   680  			BeforeEach(func() {
   681  				orgName = helpers.NewOrgName()
   682  				spaceName = helpers.NewSpaceName()
   683  				helpers.SetupCF(orgName, spaceName)
   684  
   685  				serviceInstanceName = helpers.NewServiceInstanceName()
   686  				Eventually(helpers.CF("cups", serviceInstanceName)).Should(Exit(0))
   687  			})
   688  
   689  			AfterEach(func() {
   690  				helpers.QuickDeleteOrg(orgName)
   691  			})
   692  
   693  			It("has the expected shared behaviors", func() {
   694  				testExpectedBehaviors("service-instance", "Service instance", serviceInstanceName)
   695  			})
   696  
   697  			It("sets the specified labels on the service-instance", func() {
   698  				session := helpers.CF("set-label", "service-instance", serviceInstanceName, "some-key=some-value", "some-other-key=some-other-value")
   699  				Eventually(session).Should(Say(regexp.QuoteMeta(`Setting label(s) for service-instance %s in org %s / space %s as %s...`), serviceInstanceName, orgName, spaceName, username))
   700  				Eventually(session).Should(Say("OK"))
   701  				Eventually(session).Should(Exit(0))
   702  
   703  				helpers.CheckExpectedLabels(fmt.Sprintf("/v3/service_instances?names=%s", serviceInstanceName), true, helpers.MetadataLabels{
   704  					"some-key":       "some-value",
   705  					"some-other-key": "some-other-value",
   706  				})
   707  			})
   708  
   709  			When("more than one value is provided for the same key", func() {
   710  				It("uses the last value", func() {
   711  					session := helpers.CF("set-label", "service-instance", serviceInstanceName, "owner=sue", "owner=beth")
   712  					Eventually(session).Should(Exit(0))
   713  
   714  					helpers.CheckExpectedLabels(fmt.Sprintf("/v3/service_instances?names=%s", serviceInstanceName), true, helpers.MetadataLabels{
   715  						"owner": "beth",
   716  					})
   717  				})
   718  			})
   719  		})
   720  
   721  		When("assigning label to service-offering", func() {
   722  			var (
   723  				broker              *servicebrokerstub.ServiceBrokerStub
   724  				serviceOfferingName string
   725  			)
   726  
   727  			BeforeEach(func() {
   728  				orgName = helpers.NewOrgName()
   729  				spaceName = helpers.NewSpaceName()
   730  				helpers.SetupCF(orgName, spaceName)
   731  				broker = servicebrokerstub.Register()
   732  				serviceOfferingName = broker.Services[0].Name
   733  			})
   734  
   735  			AfterEach(func() {
   736  				helpers.QuickDeleteOrg(orgName)
   737  				broker.Forget()
   738  			})
   739  
   740  			It("has the expected shared behaviors", func() {
   741  				testExpectedBehaviors("service-offering", "Service offering", serviceOfferingName)
   742  			})
   743  
   744  			It("sets the specified labels", func() {
   745  				session := helpers.CF("set-label", "service-offering", serviceOfferingName, "some-key=some-value", "some-other-key=some-other-value")
   746  				Eventually(session).Should(Say(regexp.QuoteMeta(`Setting label(s) for service-offering %s as %s...`), serviceOfferingName, username))
   747  				Eventually(session).Should(Say("OK"))
   748  				Eventually(session).Should(Exit(0))
   749  
   750  				helpers.CheckExpectedLabels(fmt.Sprintf("/v3/service_offerings?names=%s", serviceOfferingName), true, helpers.MetadataLabels{
   751  					"some-key":       "some-value",
   752  					"some-other-key": "some-other-value",
   753  				})
   754  			})
   755  
   756  			When("more than one value is provided for the same key", func() {
   757  				It("uses the last value", func() {
   758  					session := helpers.CF("set-label", "service-broker", broker.Name, "owner=sue", "owner=beth")
   759  					Eventually(session).Should(Exit(0))
   760  
   761  					helpers.CheckExpectedLabels(fmt.Sprintf("/v3/service_brokers?names=%s", broker.Name), true, helpers.MetadataLabels{
   762  						"owner": "beth",
   763  					})
   764  				})
   765  			})
   766  
   767  			When("the service broker name is specified as part of the command", func() {
   768  				It("sets the specified labels", func() {
   769  					session := helpers.CF("set-label", "-b", broker.Name, "service-offering", serviceOfferingName, "some-key=some-value", "some-other-key=some-other-value")
   770  					Eventually(session).Should(Say(regexp.QuoteMeta(`Setting label(s) for service-offering %s from service broker %s as %s...`), serviceOfferingName, broker.Name, username))
   771  					Eventually(session).Should(Say("OK"))
   772  					Eventually(session).Should(Exit(0))
   773  
   774  					helpers.CheckExpectedLabels(fmt.Sprintf("/v3/service_offerings?names=%s", serviceOfferingName), true, helpers.MetadataLabels{
   775  						"some-key":       "some-value",
   776  						"some-other-key": "some-other-value",
   777  					})
   778  				})
   779  			})
   780  		})
   781  
   782  		When("assigning label to service-plan", func() {
   783  			var (
   784  				broker              *servicebrokerstub.ServiceBrokerStub
   785  				servicePlanName     string
   786  				serviceOfferingName string
   787  			)
   788  
   789  			BeforeEach(func() {
   790  				orgName = helpers.NewOrgName()
   791  				spaceName = helpers.NewSpaceName()
   792  				helpers.SetupCF(orgName, spaceName)
   793  				broker = servicebrokerstub.Register()
   794  				servicePlanName = broker.Services[0].Plans[0].Name
   795  				serviceOfferingName = broker.Services[0].Name
   796  			})
   797  
   798  			AfterEach(func() {
   799  				helpers.QuickDeleteOrg(orgName)
   800  				broker.Forget()
   801  			})
   802  
   803  			It("has the expected shared behaviors", func() {
   804  				testExpectedBehaviors("service-plan", "Service plan", servicePlanName)
   805  			})
   806  
   807  			It("sets the specified labels", func() {
   808  				session := helpers.CF("set-label", "service-plan", servicePlanName, "-b", broker.Name, "-e", serviceOfferingName, "some-key=some-value", "some-other-key=some-other-value")
   809  				Eventually(session).Should(Say(regexp.QuoteMeta(`Setting label(s) for service-plan %s from service offering %s / service broker %s as %s...`), servicePlanName, serviceOfferingName, broker.Name, username))
   810  				Eventually(session).Should(Say("OK"))
   811  				Eventually(session).Should(Exit(0))
   812  
   813  				helpers.CheckExpectedLabels(fmt.Sprintf("/v3/service_plans?names=%s", servicePlanName), true, helpers.MetadataLabels{
   814  					"some-key":       "some-value",
   815  					"some-other-key": "some-other-value",
   816  				})
   817  			})
   818  		})
   819  
   820  	})
   821  })
   822  
   823  func deleteResourceByGUID(guid string, urlType string) {
   824  	session := helpers.CF("curl", "-v", "-X", "DELETE",
   825  		fmt.Sprintf("/v3/%s/%s", urlType, guid))
   826  	Eventually(session).Should(Exit(0))
   827  	Eventually(session).Should(Say(`(?:204 No Content|202 Accepted)`))
   828  }