github.com/mook-as/cf-cli@v7.0.0-beta.28.0.20200120190804-b91c115fae48+incompatible/integration/v7/isolated/set_label_command_test.go (about)

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