github.com/franc20/ayesa_sap@v7.0.0-beta.28.0.20200124003224-302d4d52fa6c+incompatible/api/cloudcontroller/ccv3/organization_test.go (about)

     1  package ccv3_test
     2  
     3  import (
     4  	"fmt"
     5  	"net/http"
     6  
     7  	"code.cloudfoundry.org/cli/api/cloudcontroller/ccerror"
     8  	"code.cloudfoundry.org/cli/api/cloudcontroller/ccv3"
     9  	. "code.cloudfoundry.org/cli/api/cloudcontroller/ccv3"
    10  	"code.cloudfoundry.org/cli/types"
    11  	. "github.com/onsi/ginkgo"
    12  	. "github.com/onsi/gomega"
    13  	. "github.com/onsi/gomega/ghttp"
    14  )
    15  
    16  var _ = Describe("Organizations", func() {
    17  	var client *Client
    18  
    19  	BeforeEach(func() {
    20  		client, _ = NewTestClient()
    21  	})
    22  
    23  	Describe("GetDefaultDomain", func() {
    24  		var (
    25  			defaultDomain Domain
    26  			warnings      Warnings
    27  			executeErr    error
    28  			orgGUID       = "some-org-guid"
    29  		)
    30  
    31  		JustBeforeEach(func() {
    32  			defaultDomain, warnings, executeErr = client.GetDefaultDomain(orgGUID)
    33  		})
    34  
    35  		When("organizations exist", func() {
    36  			BeforeEach(func() {
    37  				response1 := fmt.Sprintf(`
    38      {
    39        	"name": "domain-name-1",
    40        	"guid": "domain-guid-1",
    41        	"relationships": {
    42              "organization": {
    43                  "data": {
    44                      "guid": "some-org-guid"
    45                  }
    46              }
    47           },
    48  "internal": false
    49      }`)
    50  
    51  				server.AppendHandlers(
    52  					CombineHandlers(
    53  						VerifyRequest(http.MethodGet, fmt.Sprintf("/v3/organizations/%s/domains/default", orgGUID)),
    54  						RespondWith(http.StatusOK, response1, http.Header{"X-Cf-Warnings": {"this is a warning"}}),
    55  					),
    56  				)
    57  			})
    58  
    59  			It("returns the queried organizations and all warnings", func() {
    60  				Expect(executeErr).NotTo(HaveOccurred())
    61  
    62  				Expect(defaultDomain).To(Equal(
    63  					Domain{Name: "domain-name-1", GUID: "domain-guid-1", Internal: types.NullBool{IsSet: true, Value: false},
    64  						OrganizationGUID: "some-org-guid"},
    65  				))
    66  				Expect(warnings).To(ConsistOf("this is a warning"))
    67  			})
    68  		})
    69  
    70  		When("the cloud controller returns errors and warnings", func() {
    71  			BeforeEach(func() {
    72  				response := `{
    73    "errors": [
    74      {
    75        "code": 10008,
    76        "detail": "The request is semantically invalid: command presence",
    77        "title": "CF-UnprocessableEntity"
    78      },
    79      {
    80        "code": 10010,
    81        "detail": "Org not found",
    82        "title": "CF-ResourceNotFound"
    83      }
    84    ]
    85  }`
    86  				server.AppendHandlers(
    87  					CombineHandlers(
    88  						VerifyRequest(http.MethodGet, fmt.Sprintf("/v3/organizations/%s/domains/default", orgGUID)),
    89  						RespondWith(http.StatusTeapot, response, http.Header{"X-Cf-Warnings": {"this is a warning"}}),
    90  					),
    91  				)
    92  			})
    93  
    94  			It("returns the error and all warnings", func() {
    95  				Expect(executeErr).To(MatchError(ccerror.MultiError{
    96  					ResponseCode: http.StatusTeapot,
    97  					Errors: []ccerror.V3Error{
    98  						{
    99  							Code:   10008,
   100  							Detail: "The request is semantically invalid: command presence",
   101  							Title:  "CF-UnprocessableEntity",
   102  						},
   103  						{
   104  							Code:   10010,
   105  							Detail: "Org not found",
   106  							Title:  "CF-ResourceNotFound",
   107  						},
   108  					},
   109  				}))
   110  				Expect(warnings).To(ConsistOf("this is a warning"))
   111  			})
   112  		})
   113  	})
   114  
   115  	Describe("GetIsolationSegmentOrganizations", func() {
   116  		var (
   117  			organizations []Organization
   118  			warnings      Warnings
   119  			executeErr    error
   120  		)
   121  
   122  		JustBeforeEach(func() {
   123  			organizations, warnings, executeErr = client.GetIsolationSegmentOrganizations("some-iso-guid")
   124  		})
   125  
   126  		When("organizations exist", func() {
   127  			BeforeEach(func() {
   128  				response1 := fmt.Sprintf(`{
   129  	"pagination": {
   130  		"next": {
   131  			"href": "%s/v3/isolation_segments/some-iso-guid/organizations?page=2&per_page=2"
   132  		}
   133  	},
   134    "resources": [
   135      {
   136        "name": "org-name-1",
   137        "guid": "org-guid-1"
   138      },
   139      {
   140        "name": "org-name-2",
   141        "guid": "org-guid-2"
   142      }
   143    ]
   144  }`, server.URL())
   145  				response2 := `{
   146  	"pagination": {
   147  		"next": null
   148  	},
   149  	"resources": [
   150  	  {
   151        "name": "org-name-3",
   152  		  "guid": "org-guid-3"
   153  		}
   154  	]
   155  }`
   156  				server.AppendHandlers(
   157  					CombineHandlers(
   158  						VerifyRequest(http.MethodGet, "/v3/isolation_segments/some-iso-guid/organizations"),
   159  						RespondWith(http.StatusOK, response1, http.Header{"X-Cf-Warnings": {"this is a warning"}}),
   160  					),
   161  				)
   162  				server.AppendHandlers(
   163  					CombineHandlers(
   164  						VerifyRequest(http.MethodGet, "/v3/isolation_segments/some-iso-guid/organizations", "page=2&per_page=2"),
   165  						RespondWith(http.StatusOK, response2, http.Header{"X-Cf-Warnings": {"this is another warning"}}),
   166  					),
   167  				)
   168  			})
   169  
   170  			It("returns the queried organizations and all warnings", func() {
   171  				Expect(executeErr).NotTo(HaveOccurred())
   172  
   173  				Expect(organizations).To(ConsistOf(
   174  					Organization{Name: "org-name-1", GUID: "org-guid-1"},
   175  					Organization{Name: "org-name-2", GUID: "org-guid-2"},
   176  					Organization{Name: "org-name-3", GUID: "org-guid-3"},
   177  				))
   178  				Expect(warnings).To(ConsistOf("this is a warning", "this is another warning"))
   179  			})
   180  		})
   181  
   182  		When("the cloud controller returns errors and warnings", func() {
   183  			BeforeEach(func() {
   184  				response := `{
   185    "errors": [
   186      {
   187        "code": 10008,
   188        "detail": "The request is semantically invalid: command presence",
   189        "title": "CF-UnprocessableEntity"
   190      },
   191  		{
   192        "code": 10010,
   193        "detail": "Isolation segment not found",
   194        "title": "CF-ResourceNotFound"
   195      }
   196    ]
   197  }`
   198  				server.AppendHandlers(
   199  					CombineHandlers(
   200  						VerifyRequest(http.MethodGet, "/v3/isolation_segments/some-iso-guid/organizations"),
   201  						RespondWith(http.StatusTeapot, response, http.Header{"X-Cf-Warnings": {"this is a warning"}}),
   202  					),
   203  				)
   204  			})
   205  
   206  			It("returns the error and all warnings", func() {
   207  				Expect(executeErr).To(MatchError(ccerror.MultiError{
   208  					ResponseCode: http.StatusTeapot,
   209  					Errors: []ccerror.V3Error{
   210  						{
   211  							Code:   10008,
   212  							Detail: "The request is semantically invalid: command presence",
   213  							Title:  "CF-UnprocessableEntity",
   214  						},
   215  						{
   216  							Code:   10010,
   217  							Detail: "Isolation segment not found",
   218  							Title:  "CF-ResourceNotFound",
   219  						},
   220  					},
   221  				}))
   222  				Expect(warnings).To(ConsistOf("this is a warning"))
   223  			})
   224  		})
   225  	})
   226  
   227  	Describe("GetOrganization", func() {
   228  		var (
   229  			organization Organization
   230  			warnings     Warnings
   231  			executeErr   error
   232  		)
   233  
   234  		JustBeforeEach(func() {
   235  			organization, warnings, executeErr = client.GetOrganization("some-org-guid")
   236  		})
   237  
   238  		When("organization exists", func() {
   239  			BeforeEach(func() {
   240  				response := `{
   241  					"name": "some-org-name",
   242  					"guid": "some-org-guid"
   243  				}`
   244  
   245  				server.AppendHandlers(
   246  					CombineHandlers(
   247  						VerifyRequest(http.MethodGet, "/v3/organizations/some-org-guid"),
   248  						RespondWith(http.StatusOK, response, http.Header{"X-Cf-Warnings": {"this is a warning"}}),
   249  					),
   250  				)
   251  			})
   252  
   253  			It("returns the queried organization and all warnings", func() {
   254  				Expect(executeErr).NotTo(HaveOccurred())
   255  				Expect(organization).To(Equal(Organization{Name: "some-org-name", GUID: "some-org-guid"}))
   256  				Expect(warnings).To(ConsistOf("this is a warning"))
   257  			})
   258  		})
   259  
   260  		When("the cloud controller returns errors and warnings", func() {
   261  			BeforeEach(func() {
   262  				response := `{
   263  				  "errors": [
   264  					{
   265  					  "code": 10008,
   266  					  "detail": "The request is semantically invalid: command presence",
   267  					  "title": "CF-UnprocessableEntity"
   268  					},
   269  					{
   270  					  "code": 10010,
   271  					  "detail": "Org not found",
   272  					  "title": "CF-ResourceNotFound"
   273  					}
   274  				  ]
   275  				}`
   276  
   277  				server.AppendHandlers(
   278  					CombineHandlers(
   279  						VerifyRequest(http.MethodGet, "/v3/organizations/some-org-guid"),
   280  						RespondWith(http.StatusTeapot, response, http.Header{"X-Cf-Warnings": {"this is a warning"}}),
   281  					),
   282  				)
   283  			})
   284  
   285  			It("returns the error and all warnings", func() {
   286  				Expect(executeErr).To(MatchError(ccerror.MultiError{
   287  					ResponseCode: http.StatusTeapot,
   288  					Errors: []ccerror.V3Error{
   289  						{
   290  							Code:   10008,
   291  							Detail: "The request is semantically invalid: command presence",
   292  							Title:  "CF-UnprocessableEntity",
   293  						},
   294  						{
   295  							Code:   10010,
   296  							Detail: "Org not found",
   297  							Title:  "CF-ResourceNotFound",
   298  						},
   299  					},
   300  				}))
   301  				Expect(warnings).To(ConsistOf("this is a warning"))
   302  			})
   303  		})
   304  	})
   305  
   306  	Describe("GetOrganizations", func() {
   307  		var (
   308  			organizations []Organization
   309  			warnings      Warnings
   310  			executeErr    error
   311  		)
   312  
   313  		JustBeforeEach(func() {
   314  			organizations, warnings, executeErr = client.GetOrganizations(Query{
   315  				Key:    NameFilter,
   316  				Values: []string{"some-org-name"},
   317  			})
   318  		})
   319  
   320  		When("organizations exist", func() {
   321  			BeforeEach(func() {
   322  				response1 := fmt.Sprintf(`{
   323  	"pagination": {
   324  		"next": {
   325  			"href": "%s/v3/organizations?names=some-org-name&page=2&per_page=2"
   326  		}
   327  	},
   328    "resources": [
   329      {
   330        "name": "org-name-1",
   331        "guid": "org-guid-1"
   332      },
   333      {
   334        "name": "org-name-2",
   335        "guid": "org-guid-2"
   336      }
   337    ]
   338  }`, server.URL())
   339  				response2 := `{
   340  	"pagination": {
   341  		"next": null
   342  	},
   343  	"resources": [
   344  	  {
   345        "name": "org-name-3",
   346  		  "guid": "org-guid-3"
   347  		}
   348  	]
   349  }`
   350  				server.AppendHandlers(
   351  					CombineHandlers(
   352  						VerifyRequest(http.MethodGet, "/v3/organizations", "names=some-org-name"),
   353  						RespondWith(http.StatusOK, response1, http.Header{"X-Cf-Warnings": {"this is a warning"}}),
   354  					),
   355  				)
   356  				server.AppendHandlers(
   357  					CombineHandlers(
   358  						VerifyRequest(http.MethodGet, "/v3/organizations", "names=some-org-name&page=2&per_page=2"),
   359  						RespondWith(http.StatusOK, response2, http.Header{"X-Cf-Warnings": {"this is another warning"}}),
   360  					),
   361  				)
   362  			})
   363  
   364  			It("returns the queried organizations and all warnings", func() {
   365  				Expect(executeErr).NotTo(HaveOccurred())
   366  
   367  				Expect(organizations).To(ConsistOf(
   368  					Organization{Name: "org-name-1", GUID: "org-guid-1"},
   369  					Organization{Name: "org-name-2", GUID: "org-guid-2"},
   370  					Organization{Name: "org-name-3", GUID: "org-guid-3"},
   371  				))
   372  				Expect(warnings).To(ConsistOf("this is a warning", "this is another warning"))
   373  			})
   374  		})
   375  
   376  		When("the cloud controller returns errors and warnings", func() {
   377  			BeforeEach(func() {
   378  				response := `{
   379    "errors": [
   380      {
   381        "code": 10008,
   382        "detail": "The request is semantically invalid: command presence",
   383        "title": "CF-UnprocessableEntity"
   384      },
   385      {
   386        "code": 10010,
   387        "detail": "Org not found",
   388        "title": "CF-ResourceNotFound"
   389      }
   390    ]
   391  }`
   392  				server.AppendHandlers(
   393  					CombineHandlers(
   394  						VerifyRequest(http.MethodGet, "/v3/organizations"),
   395  						RespondWith(http.StatusTeapot, response, http.Header{"X-Cf-Warnings": {"this is a warning"}}),
   396  					),
   397  				)
   398  			})
   399  
   400  			It("returns the error and all warnings", func() {
   401  				Expect(executeErr).To(MatchError(ccerror.MultiError{
   402  					ResponseCode: http.StatusTeapot,
   403  					Errors: []ccerror.V3Error{
   404  						{
   405  							Code:   10008,
   406  							Detail: "The request is semantically invalid: command presence",
   407  							Title:  "CF-UnprocessableEntity",
   408  						},
   409  						{
   410  							Code:   10010,
   411  							Detail: "Org not found",
   412  							Title:  "CF-ResourceNotFound",
   413  						},
   414  					},
   415  				}))
   416  				Expect(warnings).To(ConsistOf("this is a warning"))
   417  			})
   418  		})
   419  	})
   420  
   421  	Describe("CreateOrganization", func() {
   422  		var (
   423  			createdOrg Organization
   424  			warnings   Warnings
   425  			executeErr error
   426  		)
   427  
   428  		JustBeforeEach(func() {
   429  			createdOrg, warnings, executeErr = client.CreateOrganization("some-org-name")
   430  		})
   431  
   432  		When("the organization is created successfully", func() {
   433  			BeforeEach(func() {
   434  				response := `{
   435  					"guid": "some-org-guid",
   436  					"name": "some-org-name"
   437  				}`
   438  
   439  				expectedBody := map[string]interface{}{
   440  					"name": "some-org-name",
   441  				}
   442  
   443  				server.AppendHandlers(
   444  					CombineHandlers(
   445  						VerifyRequest(http.MethodPost, "/v3/organizations"),
   446  						VerifyJSONRepresenting(expectedBody),
   447  						RespondWith(http.StatusOK, response, http.Header{"X-Cf-Warnings": {"this is a warning"}}),
   448  					),
   449  				)
   450  			})
   451  
   452  			It("returns the created org", func() {
   453  				Expect(executeErr).ToNot(HaveOccurred())
   454  				Expect(warnings).To(ConsistOf("this is a warning"))
   455  				Expect(createdOrg).To(Equal(ccv3.Organization{
   456  					GUID: "some-org-guid",
   457  					Name: "some-org-name",
   458  				}))
   459  			})
   460  		})
   461  
   462  		When("an organization with the same name already exists", func() {
   463  			BeforeEach(func() {
   464  				response := `{
   465  					 "errors": [
   466  							{
   467  								 "detail": "Organization 'some-org-name' already exists.",
   468  								 "title": "CF-UnprocessableEntity",
   469  								 "code": 10008
   470  							}
   471  					 ]
   472  				}`
   473  
   474  				expectedBody := map[string]interface{}{
   475  					"name": "some-org-name",
   476  				}
   477  
   478  				server.AppendHandlers(
   479  					CombineHandlers(
   480  						VerifyRequest(http.MethodPost, "/v3/organizations"),
   481  						VerifyJSONRepresenting(expectedBody),
   482  						RespondWith(http.StatusUnprocessableEntity, response, http.Header{"X-Cf-Warnings": {"this is a warning"}}),
   483  					),
   484  				)
   485  			})
   486  
   487  			It("returns a meaningful organization-name-taken error", func() {
   488  				Expect(executeErr).To(MatchError(ccerror.OrganizationNameTakenError{
   489  					UnprocessableEntityError: ccerror.UnprocessableEntityError{
   490  						Message: "Organization 'some-org-name' already exists.",
   491  					},
   492  				}))
   493  				Expect(warnings).To(ConsistOf("this is a warning"))
   494  			})
   495  		})
   496  
   497  		When("creating the org fails", func() {
   498  			BeforeEach(func() {
   499  				response := `{
   500  					 "errors": [
   501  							{
   502  								 "detail": "Fail",
   503  								 "title": "CF-SomeError",
   504  								 "code": 10002
   505  							},
   506  							{
   507  								 "detail": "Something went terribly wrong",
   508  								 "title": "CF-UnknownError",
   509  								 "code": 10001
   510  							}
   511  					 ]
   512  				}`
   513  
   514  				expectedBody := map[string]interface{}{
   515  					"name": "some-org-name",
   516  				}
   517  
   518  				server.AppendHandlers(
   519  					CombineHandlers(
   520  						VerifyRequest(http.MethodPost, "/v3/organizations"),
   521  						VerifyJSONRepresenting(expectedBody),
   522  						RespondWith(http.StatusTeapot, response, http.Header{"X-Cf-Warnings": {"this is a warning"}}),
   523  					),
   524  				)
   525  			})
   526  
   527  			It("returns an error", func() {
   528  				Expect(executeErr).To(MatchError(ccerror.MultiError{
   529  					ResponseCode: http.StatusTeapot,
   530  					Errors: []ccerror.V3Error{
   531  						{
   532  							Code:   10002,
   533  							Detail: "Fail",
   534  							Title:  "CF-SomeError",
   535  						},
   536  						{
   537  							Code:   10001,
   538  							Detail: "Something went terribly wrong",
   539  							Title:  "CF-UnknownError",
   540  						},
   541  					},
   542  				}))
   543  				Expect(warnings).To(ConsistOf("this is a warning"))
   544  			})
   545  		})
   546  	})
   547  
   548  	Describe("UpdateOrganization", func() {
   549  		var (
   550  			orgToUpdate Organization
   551  			updatedOrg  Organization
   552  			warnings    Warnings
   553  			executeErr  error
   554  		)
   555  
   556  		JustBeforeEach(func() {
   557  			updatedOrg, warnings, executeErr = client.UpdateOrganization(orgToUpdate)
   558  		})
   559  
   560  		When("the organization is updated successfully", func() {
   561  			BeforeEach(func() {
   562  				response := `{
   563  					"guid": "some-org-guid",
   564  					"name": "some-org-name",
   565  					"metadata": {
   566  						"labels": {
   567  							"k1":"v1",
   568  							"k2":"v2"
   569  						}
   570  					}
   571  				}`
   572  
   573  				expectedBody := map[string]interface{}{
   574  					"name": "some-org-name",
   575  					"metadata": map[string]interface{}{
   576  						"labels": map[string]string{
   577  							"k1": "v1",
   578  							"k2": "v2",
   579  						},
   580  					},
   581  				}
   582  
   583  				server.AppendHandlers(
   584  					CombineHandlers(
   585  						VerifyRequest(http.MethodPatch, "/v3/organizations/some-guid"),
   586  						VerifyJSONRepresenting(expectedBody),
   587  						RespondWith(http.StatusOK, response, http.Header{"X-Cf-Warnings": {"this is a warning"}}),
   588  					),
   589  				)
   590  
   591  				orgToUpdate = Organization{
   592  					Name: "some-org-name",
   593  					GUID: "some-guid",
   594  					Metadata: &Metadata{
   595  						Labels: map[string]types.NullString{
   596  							"k1": types.NewNullString("v1"),
   597  							"k2": types.NewNullString("v2"),
   598  						},
   599  					},
   600  				}
   601  			})
   602  
   603  			It("should include the labels in the JSON", func() {
   604  				Expect(executeErr).ToNot(HaveOccurred())
   605  				Expect(len(warnings)).To(Equal(0))
   606  				Expect(updatedOrg.Metadata.Labels).To(BeEquivalentTo(
   607  					map[string]types.NullString{
   608  						"k1": types.NewNullString("v1"),
   609  						"k2": types.NewNullString("v2"),
   610  					}))
   611  			})
   612  		})
   613  	})
   614  
   615  	Describe("DeleteOrganization", func() {
   616  		var (
   617  			jobURL     JobURL
   618  			warnings   Warnings
   619  			executeErr error
   620  		)
   621  
   622  		JustBeforeEach(func() {
   623  			jobURL, warnings, executeErr = client.DeleteOrganization("org-guid")
   624  		})
   625  
   626  		When("no errors are encountered", func() {
   627  			BeforeEach(func() {
   628  				server.AppendHandlers(
   629  					CombineHandlers(
   630  						VerifyRequest(http.MethodDelete, "/v3/organizations/org-guid"),
   631  						RespondWith(http.StatusAccepted, nil, http.Header{"X-Cf-Warnings": {"warning-1, warning-2"}, "Location": []string{"job-url"}}),
   632  					))
   633  			})
   634  
   635  			It("deletes the Org and returns all warnings", func() {
   636  				Expect(executeErr).NotTo(HaveOccurred())
   637  				Expect(warnings).To(ConsistOf(Warnings{"warning-1", "warning-2"}))
   638  				Expect(jobURL).To(Equal(JobURL("job-url")))
   639  			})
   640  		})
   641  
   642  		When("an error is encountered", func() {
   643  			BeforeEach(func() {
   644  				response := `{
   645     "errors": [
   646        {
   647           "detail": "Organization not found",
   648           "title": "CF-ResourceNotFound",
   649           "code": 10010
   650        }
   651     ]
   652  }`
   653  				server.AppendHandlers(
   654  					CombineHandlers(
   655  						VerifyRequest(http.MethodDelete, "/v3/organizations/org-guid"),
   656  						RespondWith(http.StatusNotFound, response, http.Header{"X-Cf-Warnings": {"warning-1, warning-2"}}),
   657  					))
   658  			})
   659  
   660  			It("returns an error and all warnings", func() {
   661  				Expect(executeErr).To(MatchError(ccerror.ResourceNotFoundError{
   662  					Message: "Organization not found",
   663  				}))
   664  				Expect(warnings).To(ConsistOf(Warnings{"warning-1", "warning-2"}))
   665  			})
   666  		})
   667  	})
   668  })