github.com/LukasHeimann/cloudfoundrycli@v7.1.0+incompatible/api/cloudcontroller/ccv3/domain_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/resources"
     9  	"code.cloudfoundry.org/cli/types"
    10  
    11  	. "code.cloudfoundry.org/cli/api/cloudcontroller/ccv3"
    12  	. "github.com/onsi/ginkgo"
    13  	. "github.com/onsi/gomega"
    14  	. "github.com/onsi/gomega/ghttp"
    15  )
    16  
    17  var _ = Describe("Domain", func() {
    18  	var client *Client
    19  
    20  	BeforeEach(func() {
    21  		client, _ = NewTestClient()
    22  	})
    23  
    24  	Describe("CheckRoute", func() {
    25  		var (
    26  			matches    bool
    27  			warnings   Warnings
    28  			executeErr error
    29  
    30  			domainGUID string
    31  			hostname   string
    32  			path       string
    33  			port       int
    34  		)
    35  
    36  		BeforeEach(func() {
    37  			domainGUID = "domain-guid"
    38  			hostname = ""
    39  			path = ""
    40  			port = 0
    41  		})
    42  
    43  		JustBeforeEach(func() {
    44  			matches, warnings, executeErr = client.CheckRoute(domainGUID, hostname, path, port)
    45  		})
    46  
    47  		When("the request succeeds", func() {
    48  			When("no query params given", func() {
    49  				BeforeEach(func() {
    50  					response := `{ "matching_route": true }`
    51  
    52  					server.AppendHandlers(
    53  						CombineHandlers(
    54  							VerifyRequest(http.MethodGet, "/v3/domains/domain-guid/route_reservations"),
    55  							RespondWith(http.StatusOK, response, http.Header{"X-Cf-Warnings": {"warning-1"}}),
    56  						),
    57  					)
    58  				})
    59  
    60  				It("returns whether the route matches and all warnings", func() {
    61  					Expect(matches).To(BeTrue())
    62  					Expect(executeErr).ToNot(HaveOccurred())
    63  					Expect(warnings).To(ConsistOf("warning-1"))
    64  				})
    65  			})
    66  
    67  			When("hostname is passed in", func() {
    68  				BeforeEach(func() {
    69  					hostname = "hello"
    70  					response := `{ "matching_route": true }`
    71  
    72  					server.AppendHandlers(
    73  						CombineHandlers(
    74  							VerifyRequest(http.MethodGet, "/v3/domains/domain-guid/route_reservations", "host=hello"),
    75  							RespondWith(http.StatusOK, response, http.Header{"X-Cf-Warnings": {"warning-1"}}),
    76  						),
    77  					)
    78  				})
    79  
    80  				It("returns whether the route matches and all warnings", func() {
    81  					Expect(matches).To(BeTrue())
    82  					Expect(executeErr).ToNot(HaveOccurred())
    83  					Expect(warnings).To(ConsistOf("warning-1"))
    84  				})
    85  			})
    86  
    87  			When("path is passed in", func() {
    88  				BeforeEach(func() {
    89  					path = "/potato"
    90  					response := `{ "matching_route": true }`
    91  
    92  					server.AppendHandlers(
    93  						CombineHandlers(
    94  							VerifyRequest(http.MethodGet, "/v3/domains/domain-guid/route_reservations", "path=/potato"),
    95  							RespondWith(http.StatusOK, response, http.Header{"X-Cf-Warnings": {"warning-1"}}),
    96  						),
    97  					)
    98  				})
    99  
   100  				It("returns whether the route matches and all warnings", func() {
   101  					Expect(matches).To(BeTrue())
   102  					Expect(executeErr).ToNot(HaveOccurred())
   103  					Expect(warnings).To(ConsistOf("warning-1"))
   104  				})
   105  			})
   106  
   107  			When("hostname and path are passed in", func() {
   108  				BeforeEach(func() {
   109  					hostname = "hello"
   110  					path = "/potato"
   111  					response := `{ "matching_route": true }`
   112  
   113  					server.AppendHandlers(
   114  						CombineHandlers(
   115  							VerifyRequest(http.MethodGet, "/v3/domains/domain-guid/route_reservations", "host=hello&path=/potato"),
   116  							RespondWith(http.StatusOK, response, http.Header{"X-Cf-Warnings": {"warning-1"}}),
   117  						),
   118  					)
   119  				})
   120  
   121  				It("returns whether the route matches and all warnings", func() {
   122  					Expect(matches).To(BeTrue())
   123  					Expect(executeErr).ToNot(HaveOccurred())
   124  					Expect(warnings).To(ConsistOf("warning-1"))
   125  				})
   126  			})
   127  
   128  			When("port is passed in", func() {
   129  				BeforeEach(func() {
   130  					port = 1024
   131  					response := `{ "matching_route": true }`
   132  
   133  					server.AppendHandlers(
   134  						CombineHandlers(
   135  							VerifyRequest(http.MethodGet, "/v3/domains/domain-guid/route_reservations", "port=1024"),
   136  							RespondWith(http.StatusOK, response, http.Header{"X-Cf-Warnings": {"warning-1"}}),
   137  						),
   138  					)
   139  				})
   140  
   141  				It("returns whether the route matches and all warnings", func() {
   142  					Expect(matches).To(BeTrue())
   143  					Expect(executeErr).ToNot(HaveOccurred())
   144  					Expect(warnings).To(ConsistOf("warning-1"))
   145  				})
   146  			})
   147  		})
   148  
   149  		When("the cloud controller returns errors and warnings", func() {
   150  			BeforeEach(func() {
   151  				response := `{
   152    "errors": [
   153      {
   154        "code": 10008,
   155        "detail": "The request is semantically invalid: command presence",
   156        "title": "CF-UnprocessableEntity"
   157      },
   158  	{
   159        "code": 10010,
   160        "detail": "Domain not found",
   161        "title": "CF-ResourceNotFound"
   162      }
   163    ]
   164  }`
   165  				server.AppendHandlers(
   166  					CombineHandlers(
   167  						VerifyRequest(http.MethodGet, "/v3/domains/domain-guid/route_reservations"),
   168  						RespondWith(http.StatusTeapot, response, http.Header{"X-Cf-Warnings": {"this is a warning"}}),
   169  					),
   170  				)
   171  			})
   172  
   173  			It("returns the error and all warnings", func() {
   174  				Expect(executeErr).To(MatchError(ccerror.MultiError{
   175  					ResponseCode: http.StatusTeapot,
   176  					Errors: []ccerror.V3Error{
   177  						{
   178  							Code:   10008,
   179  							Detail: "The request is semantically invalid: command presence",
   180  							Title:  "CF-UnprocessableEntity",
   181  						},
   182  						{
   183  							Code:   10010,
   184  							Detail: "Domain not found",
   185  							Title:  "CF-ResourceNotFound",
   186  						},
   187  					},
   188  				}))
   189  				Expect(warnings).To(ConsistOf("this is a warning"))
   190  			})
   191  		})
   192  	})
   193  
   194  	Describe("CreateDomain for Shared Domains", func() {
   195  		var (
   196  			domain     resources.Domain
   197  			warnings   Warnings
   198  			executeErr error
   199  		)
   200  
   201  		JustBeforeEach(func() {
   202  			domain, warnings, executeErr = client.CreateDomain(
   203  				resources.Domain{
   204  					Name:        "some-name",
   205  					Internal:    types.NullBool{IsSet: true, Value: true},
   206  					RouterGroup: "some-router-group",
   207  				},
   208  			)
   209  		})
   210  
   211  		When("the request succeeds", func() {
   212  			BeforeEach(func() {
   213  				response := `{
   214  					"guid": "some-guid",
   215  					"name": "some-name",
   216  					"internal": true,
   217  					"router_group": {
   218  						"guid": "some-router-group"
   219  					}
   220  				}`
   221  
   222  				expectedBody := `{
   223  					"name": "some-name",
   224  					"internal": true,
   225  					"router_group": {
   226  						"guid": "some-router-group"
   227  					}
   228  				}`
   229  
   230  				server.AppendHandlers(
   231  					CombineHandlers(
   232  						VerifyRequest(http.MethodPost, "/v3/domains"),
   233  						VerifyJSON(expectedBody),
   234  						RespondWith(http.StatusCreated, response, http.Header{"X-Cf-Warnings": {"warning-1"}}),
   235  					),
   236  				)
   237  			})
   238  
   239  			It("returns the given domain and all warnings", func() {
   240  				Expect(executeErr).ToNot(HaveOccurred())
   241  				Expect(warnings).To(ConsistOf("warning-1"))
   242  
   243  				Expect(domain).To(Equal(resources.Domain{
   244  					GUID:        "some-guid",
   245  					Name:        "some-name",
   246  					Internal:    types.NullBool{IsSet: true, Value: true},
   247  					RouterGroup: "some-router-group",
   248  				}))
   249  			})
   250  		})
   251  
   252  		When("the cloud controller returns errors and warnings", func() {
   253  			BeforeEach(func() {
   254  				response := `{
   255    "errors": [
   256      {
   257        "code": 10008,
   258        "detail": "The request is semantically invalid: command presence",
   259        "title": "CF-UnprocessableEntity"
   260      },
   261  		{
   262        "code": 10010,
   263        "detail": "Isolation segment not found",
   264        "title": "CF-ResourceNotFound"
   265      }
   266    ]
   267  }`
   268  				server.AppendHandlers(
   269  					CombineHandlers(
   270  						VerifyRequest(http.MethodPost, "/v3/domains"),
   271  						RespondWith(http.StatusTeapot, response, http.Header{"X-Cf-Warnings": {"this is a warning"}}),
   272  					),
   273  				)
   274  			})
   275  
   276  			It("returns the error and all warnings", func() {
   277  				Expect(executeErr).To(MatchError(ccerror.MultiError{
   278  					ResponseCode: http.StatusTeapot,
   279  					Errors: []ccerror.V3Error{
   280  						{
   281  							Code:   10008,
   282  							Detail: "The request is semantically invalid: command presence",
   283  							Title:  "CF-UnprocessableEntity",
   284  						},
   285  						{
   286  							Code:   10010,
   287  							Detail: "Isolation segment not found",
   288  							Title:  "CF-ResourceNotFound",
   289  						},
   290  					},
   291  				}))
   292  				Expect(warnings).To(ConsistOf("this is a warning"))
   293  			})
   294  		})
   295  	})
   296  
   297  	Describe("CreateDomain for Private Domains", func() {
   298  		var (
   299  			domain     resources.Domain
   300  			warnings   Warnings
   301  			executeErr error
   302  		)
   303  
   304  		JustBeforeEach(func() {
   305  			domain, warnings, executeErr = client.CreateDomain(resources.Domain{Name: "some-name", Internal: types.NullBool{IsSet: false, Value: true}, OrganizationGUID: "organization-guid"})
   306  		})
   307  
   308  		When("the request succeeds", func() {
   309  			BeforeEach(func() {
   310  				response := `{
   311  					"guid": "some-guid",
   312  					"name": "some-name",
   313  					"relationships": {
   314  						"organization": {
   315  							"data" : {
   316  								"guid" : "organization-guid"
   317  							}
   318  						}
   319  					},
   320  					"internal": false
   321  				}`
   322  
   323  				expectedRequestBody := `{
   324  					"name": "some-name",
   325  					"relationships": {
   326  						"organization": {
   327  							"data" : {
   328  								"guid" : "organization-guid"
   329  							}
   330  						}
   331  					}
   332  				}`
   333  
   334  				server.AppendHandlers(
   335  					CombineHandlers(
   336  						VerifyRequest(http.MethodPost, "/v3/domains"),
   337  						VerifyJSON(expectedRequestBody),
   338  						RespondWith(http.StatusCreated, response, http.Header{"X-Cf-Warnings": {"warning-1"}}),
   339  					),
   340  				)
   341  			})
   342  
   343  			It("returns the given domain and all warnings", func() {
   344  				Expect(executeErr).ToNot(HaveOccurred())
   345  				Expect(warnings).To(ConsistOf("warning-1"))
   346  
   347  				Expect(domain).To(Equal(resources.Domain{
   348  					GUID:             "some-guid",
   349  					Name:             "some-name",
   350  					OrganizationGUID: "organization-guid",
   351  					Internal:         types.NullBool{IsSet: true, Value: false},
   352  				}))
   353  			})
   354  		})
   355  
   356  		When("the cloud controller returns errors and warnings", func() {
   357  			BeforeEach(func() {
   358  				response := `{
   359    "errors": [
   360      {
   361        "code": 10008,
   362        "detail": "The request is semantically invalid: command presence",
   363        "title": "CF-UnprocessableEntity"
   364      },
   365  		{
   366        "code": 10010,
   367        "detail": "Isolation segment not found",
   368        "title": "CF-ResourceNotFound"
   369      }
   370    ]
   371  }`
   372  				server.AppendHandlers(
   373  					CombineHandlers(
   374  						VerifyRequest(http.MethodPost, "/v3/domains"),
   375  						RespondWith(http.StatusTeapot, response, http.Header{"X-Cf-Warnings": {"this is a warning"}}),
   376  					),
   377  				)
   378  			})
   379  
   380  			It("returns the error and all warnings", func() {
   381  				Expect(executeErr).To(MatchError(ccerror.MultiError{
   382  					ResponseCode: http.StatusTeapot,
   383  					Errors: []ccerror.V3Error{
   384  						{
   385  							Code:   10008,
   386  							Detail: "The request is semantically invalid: command presence",
   387  							Title:  "CF-UnprocessableEntity",
   388  						},
   389  						{
   390  							Code:   10010,
   391  							Detail: "Isolation segment not found",
   392  							Title:  "CF-ResourceNotFound",
   393  						},
   394  					},
   395  				}))
   396  				Expect(warnings).To(ConsistOf("this is a warning"))
   397  			})
   398  		})
   399  	})
   400  
   401  	Describe("DeleteDomain", func() {
   402  		var (
   403  			domainGUID   string
   404  			jobURLString string
   405  			jobURL       JobURL
   406  			warnings     Warnings
   407  			executeErr   error
   408  		)
   409  
   410  		JustBeforeEach(func() {
   411  			jobURL, warnings, executeErr = client.DeleteDomain(domainGUID)
   412  		})
   413  
   414  		When("domain exists", func() {
   415  			domainGUID = "domain-guid"
   416  			jobURLString = "https://api.test.com/v3/jobs/job-guid"
   417  
   418  			BeforeEach(func() {
   419  				server.AppendHandlers(
   420  					CombineHandlers(
   421  						VerifyRequest(http.MethodDelete, "/v3/domains/domain-guid"),
   422  						RespondWith(http.StatusAccepted, nil, http.Header{
   423  							"X-Cf-Warnings": {"this is a warning"},
   424  							"Location":      {jobURLString},
   425  						}),
   426  					),
   427  				)
   428  			})
   429  
   430  			It("returns all warnings", func() {
   431  				Expect(executeErr).NotTo(HaveOccurred())
   432  				Expect(jobURL).To(Equal(JobURL(jobURLString)))
   433  				Expect(warnings).To(ConsistOf("this is a warning"))
   434  			})
   435  		})
   436  
   437  		When("the cloud controller returns errors and warnings", func() {
   438  			BeforeEach(func() {
   439  				response := `{
   440  	  "errors": [
   441  	    {
   442  	      "code": 10008,
   443  	      "detail": "The request is semantically invalid: command presence",
   444  	      "title": "CF-UnprocessableEntity"
   445  	    },
   446  			{
   447  	      "code": 10010,
   448  	      "detail": "Isolation segment not found",
   449  	      "title": "CF-ResourceNotFound"
   450  	    }
   451  	  ]
   452  	}`
   453  				server.AppendHandlers(
   454  					CombineHandlers(
   455  						VerifyRequest(http.MethodDelete, "/v3/domains/domain-guid"),
   456  						RespondWith(http.StatusTeapot, response, http.Header{"X-Cf-Warnings": {"this is a warning"}}),
   457  					),
   458  				)
   459  			})
   460  
   461  			It("returns the error and all warnings", func() {
   462  				Expect(executeErr).To(MatchError(ccerror.MultiError{
   463  					ResponseCode: http.StatusTeapot,
   464  					Errors: []ccerror.V3Error{
   465  						{
   466  							Code:   10008,
   467  							Detail: "The request is semantically invalid: command presence",
   468  							Title:  "CF-UnprocessableEntity",
   469  						},
   470  						{
   471  							Code:   10010,
   472  							Detail: "Isolation segment not found",
   473  							Title:  "CF-ResourceNotFound",
   474  						},
   475  					},
   476  				}))
   477  				Expect(warnings).To(ConsistOf("this is a warning"))
   478  			})
   479  		})
   480  	})
   481  
   482  	Describe("GetDomains", func() {
   483  		var (
   484  			query      Query
   485  			domains    []resources.Domain
   486  			warnings   Warnings
   487  			executeErr error
   488  		)
   489  
   490  		JustBeforeEach(func() {
   491  			domains, warnings, executeErr = client.GetDomains(query)
   492  		})
   493  
   494  		When("domains exist", func() {
   495  			BeforeEach(func() {
   496  				response1 := fmt.Sprintf(`{
   497  		"pagination": {
   498  			"next": {
   499  				"href": "%s/v3/domains?page=2&per_page=2"
   500  			}
   501  		},
   502  	  "resources": [
   503  	    {
   504  	      	"name": "domain-name-1",
   505  	      	"guid": "domain-guid-1",
   506  	      	"relationships": {
   507  	            "organization": {
   508  	                "data": {
   509  	                    "guid": "owning-org-1"
   510  	                }
   511  	            }
   512  	         }
   513  	    },
   514  	    {
   515  	      	"name": "domain-name-2",
   516  	      	"guid": "domain-guid-2",
   517  			"relationships": {
   518  	            "organization": {
   519  	                "data": {
   520  	                    "guid": "owning-org-2"
   521  	                }
   522  	            }
   523  	         }
   524  	    }
   525  	  ]
   526  	}`, server.URL())
   527  				response2 := `{
   528  		"pagination": {
   529  			"next": null
   530  		},
   531  		"resources": [
   532  		  {
   533  			"name": "domain-name-3",
   534  	         "guid": "domain-guid-3",
   535  			"relationships": {
   536  	            "organization": {
   537  	                "data": {
   538  	                    "guid": "owning-org-3"
   539  	                }
   540  	            }
   541  	         }
   542  			}
   543  		]
   544  	}`
   545  
   546  				server.AppendHandlers(
   547  					CombineHandlers(
   548  						VerifyRequest(http.MethodGet, "/v3/domains"),
   549  						RespondWith(http.StatusOK, response1, http.Header{"X-Cf-Warnings": {"this is a warning"}}),
   550  					),
   551  				)
   552  				server.AppendHandlers(
   553  					CombineHandlers(
   554  						VerifyRequest(http.MethodGet, "/v3/domains", "page=2&per_page=2"),
   555  						RespondWith(http.StatusOK, response2, http.Header{"X-Cf-Warnings": {"this is another warning"}}),
   556  					),
   557  				)
   558  
   559  				query = Query{}
   560  			})
   561  
   562  			It("returns the queried domain and all warnings", func() {
   563  				Expect(executeErr).NotTo(HaveOccurred())
   564  
   565  				Expect(domains).To(ConsistOf(
   566  					resources.Domain{Name: "domain-name-1", GUID: "domain-guid-1", OrganizationGUID: "owning-org-1"},
   567  					resources.Domain{Name: "domain-name-2", GUID: "domain-guid-2", OrganizationGUID: "owning-org-2"},
   568  					resources.Domain{Name: "domain-name-3", GUID: "domain-guid-3", OrganizationGUID: "owning-org-3"},
   569  				))
   570  				Expect(warnings).To(ConsistOf("this is a warning", "this is another warning"))
   571  			})
   572  		})
   573  
   574  		When("the cloud controller returns errors and warnings", func() {
   575  			BeforeEach(func() {
   576  				response := `{
   577  	  "errors": [
   578  	    {
   579  	      "code": 10008,
   580  	      "detail": "The request is semantically invalid: command presence",
   581  	      "title": "CF-UnprocessableEntity"
   582  	    },
   583  			{
   584  	      "code": 10010,
   585  	      "detail": "Isolation segment not found",
   586  	      "title": "CF-ResourceNotFound"
   587  	    }
   588  	  ]
   589  	}`
   590  				server.AppendHandlers(
   591  					CombineHandlers(
   592  						VerifyRequest(http.MethodGet, "/v3/domains"),
   593  						RespondWith(http.StatusTeapot, response, http.Header{"X-Cf-Warnings": {"this is a warning"}}),
   594  					),
   595  				)
   596  			})
   597  
   598  			It("returns the error and all warnings", func() {
   599  				Expect(executeErr).To(MatchError(ccerror.MultiError{
   600  					ResponseCode: http.StatusTeapot,
   601  					Errors: []ccerror.V3Error{
   602  						{
   603  							Code:   10008,
   604  							Detail: "The request is semantically invalid: command presence",
   605  							Title:  "CF-UnprocessableEntity",
   606  						},
   607  						{
   608  							Code:   10010,
   609  							Detail: "Isolation segment not found",
   610  							Title:  "CF-ResourceNotFound",
   611  						},
   612  					},
   613  				}))
   614  				Expect(warnings).To(ConsistOf("this is a warning"))
   615  			})
   616  		})
   617  	})
   618  
   619  	Describe("GetDomain", func() {
   620  
   621  		var (
   622  			domainGUID string
   623  			domain     resources.Domain
   624  			warnings   Warnings
   625  			executeErr error
   626  		)
   627  		JustBeforeEach(func() {
   628  			domainGUID = "domain-guid-1"
   629  			domain, warnings, executeErr = client.GetDomain(domainGUID)
   630  		})
   631  
   632  		When("domain is found", func() {
   633  			BeforeEach(func() {
   634  				response := `{
   635  	      	"name": "domain-name-1",
   636  	      	"guid": "domain-guid-1",
   637  					"metadata": {
   638  						"annotations": {},
   639  						"labels": {
   640  							"fun": "superfun",
   641  							"fun2": "super--fun"
   642  						}
   643  					}
   644  	    }`
   645  				server.AppendHandlers(
   646  					CombineHandlers(
   647  						VerifyRequest(http.MethodGet, "/v3/domains/domain-guid-1"),
   648  						RespondWith(http.StatusOK, response, http.Header{"X-Cf-Warnings": {"this is a warning"}}),
   649  					),
   650  				)
   651  			})
   652  
   653  			It("returns a domain and prints all warnings", func() {
   654  				Expect(executeErr).To(Not(HaveOccurred()))
   655  
   656  				Expect(domain.Name).To(Equal("domain-name-1"))
   657  
   658  				Expect(domain.GUID).To(Equal("domain-guid-1"))
   659  
   660  				Expect(domain.Metadata.Labels).To(Equal(map[string]types.NullString{
   661  					"fun":  types.NewNullString("superfun"),
   662  					"fun2": types.NewNullString("super--fun"),
   663  				}))
   664  
   665  				Expect(warnings).To(ConsistOf("this is a warning"))
   666  			})
   667  		})
   668  
   669  		When("cloud controller returns an error", func() {
   670  			BeforeEach(func() {
   671  				response := `{
   672  	  "errors": [
   673  	    {
   674  	      "code": 10008,
   675  	      "detail": "The request is semantically invalid: command presence",
   676  	      "title": "CF-UnprocessableEntity"
   677  	    },
   678  			{
   679  	      "code": 10010,
   680  	      "detail": "Domain not found",
   681  	      "title": "CF-ResourceNotFound"
   682  	    }
   683  	  ]
   684  	}`
   685  				server.AppendHandlers(
   686  					CombineHandlers(
   687  						VerifyRequest(http.MethodGet, "/v3/domains/domain-guid-1"),
   688  						RespondWith(http.StatusTeapot, response, http.Header{"X-Cf-Warnings": {"this is a warning"}}),
   689  					),
   690  				)
   691  			})
   692  
   693  			It("returns the error and all warnings", func() {
   694  				Expect(executeErr).To(MatchError(ccerror.MultiError{
   695  					ResponseCode: http.StatusTeapot,
   696  					Errors: []ccerror.V3Error{
   697  						{
   698  							Code:   10008,
   699  							Detail: "The request is semantically invalid: command presence",
   700  							Title:  "CF-UnprocessableEntity",
   701  						},
   702  						{
   703  							Code:   10010,
   704  							Detail: "Domain not found",
   705  							Title:  "CF-ResourceNotFound",
   706  						},
   707  					},
   708  				}))
   709  				Expect(warnings).To(ConsistOf("this is a warning"))
   710  			})
   711  		})
   712  	})
   713  
   714  	Describe("GetOrganizationDomains", func() {
   715  		var (
   716  			orgGUID    string
   717  			query      Query
   718  			domains    []resources.Domain
   719  			warnings   Warnings
   720  			executeErr error
   721  		)
   722  
   723  		BeforeEach(func() {
   724  			orgGUID = "some-org-guid"
   725  		})
   726  
   727  		JustBeforeEach(func() {
   728  			domains, warnings, executeErr = client.GetOrganizationDomains(orgGUID, query)
   729  		})
   730  
   731  		When("domains exist", func() {
   732  			BeforeEach(func() {
   733  				response1 := fmt.Sprintf(`{
   734  	"pagination": {
   735  		"next": {
   736  			"href": "%s/v3/organizations/some-org-guid/domains?organization_guids=some-org-guid&page=2&per_page=2"
   737  		}
   738  	},
   739    "resources": [
   740      {
   741        	"name": "domain-name-1",
   742        	"guid": "domain-guid-1",
   743        	"relationships": {
   744              "organization": {
   745                  "data": {
   746                      "guid": "some-org-guid"
   747                  }
   748              }
   749           }
   750      },
   751      {
   752        	"name": "domain-name-2",
   753        	"guid": "domain-guid-2",
   754  		"relationships": {
   755              "organization": {
   756                  "data": {
   757                      "guid": "some-org-guid"
   758                  }
   759              }
   760           }
   761      }
   762    ]
   763  }`, server.URL())
   764  				response2 := `{
   765  	"pagination": {
   766  		"next": null
   767  	},
   768  	"resources": [
   769  		{
   770  			"name": "domain-name-3",
   771  			"guid": "domain-guid-3",
   772  			"relationships": {
   773              	"organization": {
   774                  	"data": {
   775                      	"guid": "some-org-guid"
   776                  	}
   777              	}
   778           	}
   779  		}
   780  	]
   781  }`
   782  
   783  				server.AppendHandlers(
   784  					CombineHandlers(
   785  						VerifyRequest(http.MethodGet, "/v3/organizations/some-org-guid/domains", "organization_guids=some-org-guid"),
   786  						RespondWith(http.StatusOK, response1, http.Header{"X-Cf-Warnings": {"this is a warning"}}),
   787  					),
   788  				)
   789  				server.AppendHandlers(
   790  					CombineHandlers(
   791  						VerifyRequest(http.MethodGet, "/v3/organizations/some-org-guid/domains", "organization_guids=some-org-guid&page=2&per_page=2"),
   792  						RespondWith(http.StatusOK, response2, http.Header{"X-Cf-Warnings": {"this is another warning"}}),
   793  					),
   794  				)
   795  
   796  				query = Query{
   797  					Key:    OrganizationGUIDFilter,
   798  					Values: []string{orgGUID},
   799  				}
   800  			})
   801  
   802  			It("returns the queried domain and all warnings", func() {
   803  				Expect(executeErr).NotTo(HaveOccurred())
   804  
   805  				Expect(domains).To(ConsistOf(
   806  					resources.Domain{Name: "domain-name-1", GUID: "domain-guid-1", OrganizationGUID: orgGUID},
   807  					resources.Domain{Name: "domain-name-2", GUID: "domain-guid-2", OrganizationGUID: orgGUID},
   808  					resources.Domain{Name: "domain-name-3", GUID: "domain-guid-3", OrganizationGUID: orgGUID},
   809  				))
   810  				Expect(warnings).To(ConsistOf("this is a warning", "this is another warning"))
   811  			})
   812  		})
   813  
   814  		When("the cloud controller returns errors and warnings", func() {
   815  			BeforeEach(func() {
   816  				response := `{
   817    	"errors": [
   818      	{
   819        		"code": 10008,
   820        		"detail": "The request is semantically invalid: command presence",
   821        		"title": "CF-UnprocessableEntity"
   822      	},
   823  		{
   824  			"code": 10010,
   825        		"detail": "Isolation segment not found",
   826        		"title": "CF-ResourceNotFound"
   827      	}
   828    	]
   829  }`
   830  				server.AppendHandlers(
   831  					CombineHandlers(
   832  						VerifyRequest(http.MethodGet, "/v3/organizations/some-org-guid/domains"),
   833  						RespondWith(http.StatusTeapot, response, http.Header{"X-Cf-Warnings": {"this is a warning"}}),
   834  					),
   835  				)
   836  			})
   837  
   838  			It("returns the error and all warnings", func() {
   839  				Expect(executeErr).To(MatchError(ccerror.MultiError{
   840  					ResponseCode: http.StatusTeapot,
   841  					Errors: []ccerror.V3Error{
   842  						{
   843  							Code:   10008,
   844  							Detail: "The request is semantically invalid: command presence",
   845  							Title:  "CF-UnprocessableEntity",
   846  						},
   847  						{
   848  							Code:   10010,
   849  							Detail: "Isolation segment not found",
   850  							Title:  "CF-ResourceNotFound",
   851  						},
   852  					},
   853  				}))
   854  				Expect(warnings).To(ConsistOf("this is a warning"))
   855  			})
   856  		})
   857  	})
   858  
   859  	Describe("SharePrivateDomainToOrgs", func() {
   860  		var (
   861  			orgGUID    = "some-org-guid"
   862  			domainGUID = "some-domain-guid"
   863  			warnings   Warnings
   864  			executeErr error
   865  		)
   866  
   867  		JustBeforeEach(func() {
   868  			warnings, executeErr = client.SharePrivateDomainToOrgs(
   869  				domainGUID,
   870  				SharedOrgs{GUIDs: []string{orgGUID}},
   871  			)
   872  		})
   873  
   874  		When("the request succeeds", func() {
   875  			BeforeEach(func() {
   876  				response := `{"data":
   877  								[{
   878  									"guid": "some-org-guid"
   879  								}]
   880  						}`
   881  
   882  				expectedBody := `{
   883  					"data": [
   884  						{"guid": "some-org-guid"}
   885  					]
   886  				}`
   887  
   888  				server.AppendHandlers(
   889  					CombineHandlers(
   890  						VerifyRequest(http.MethodPost, "/v3/domains/some-domain-guid/relationships/shared_organizations"),
   891  						VerifyJSON(expectedBody),
   892  						RespondWith(http.StatusOK, response, http.Header{"X-Cf-Warnings": {"this is a warning"}}),
   893  					),
   894  				)
   895  			})
   896  
   897  			It("returns all warnings", func() {
   898  				Expect(warnings).To(ConsistOf("this is a warning"))
   899  				Expect(executeErr).To(BeNil())
   900  			})
   901  		})
   902  
   903  		When("the cloud controller returns errors and warnings", func() {
   904  			BeforeEach(func() {
   905  				response := `{
   906    	"errors": [
   907      	{
   908        		"code": 10008,
   909        		"detail": "The request is semantically invalid: command presence",
   910        		"title": "CF-UnprocessableEntity"
   911      	},
   912  		{
   913  			"code": 10010,
   914        		"detail": "Organization not found",
   915        		"title": "CF-ResourceNotFound"
   916      	}
   917    	]
   918  }`
   919  				server.AppendHandlers(
   920  					CombineHandlers(
   921  						VerifyRequest(http.MethodPost, "/v3/domains/some-domain-guid/relationships/shared_organizations"),
   922  						RespondWith(http.StatusTeapot, response, http.Header{"X-Cf-Warnings": {"this is a warning"}}),
   923  					),
   924  				)
   925  			})
   926  
   927  			It("returns the error and all warnings", func() {
   928  				Expect(executeErr).To(MatchError(ccerror.MultiError{
   929  					ResponseCode: http.StatusTeapot,
   930  					Errors: []ccerror.V3Error{
   931  						{
   932  							Code:   10008,
   933  							Detail: "The request is semantically invalid: command presence",
   934  							Title:  "CF-UnprocessableEntity",
   935  						},
   936  						{
   937  							Code:   10010,
   938  							Detail: "Organization not found",
   939  							Title:  "CF-ResourceNotFound",
   940  						},
   941  					},
   942  				}))
   943  				Expect(warnings).To(ConsistOf("this is a warning"))
   944  			})
   945  		})
   946  	})
   947  
   948  	Describe("UnsharePrivateDomainFromOrg", func() {
   949  		var (
   950  			orgGUID    = "some-org-guid"
   951  			domainGUID = "some-domain-guid"
   952  			warnings   Warnings
   953  			executeErr error
   954  		)
   955  
   956  		JustBeforeEach(func() {
   957  			warnings, executeErr = client.UnsharePrivateDomainFromOrg(
   958  				domainGUID,
   959  				orgGUID,
   960  			)
   961  		})
   962  
   963  		When("the request succeeds", func() {
   964  			BeforeEach(func() {
   965  				server.AppendHandlers(
   966  					CombineHandlers(
   967  						VerifyRequest(http.MethodDelete, "/v3/domains/some-domain-guid/relationships/shared_organizations/some-org-guid"),
   968  						RespondWith(http.StatusNoContent, "", http.Header{"X-Cf-Warnings": {"this is a warning"}}),
   969  					),
   970  				)
   971  			})
   972  
   973  			It("returns all warnings", func() {
   974  				Expect(warnings).To(ConsistOf("this is a warning"))
   975  				Expect(executeErr).To(BeNil())
   976  			})
   977  		})
   978  
   979  		When("the cloud controller returns errors and warnings", func() {
   980  			BeforeEach(func() {
   981  				response := `{
   982    	"errors": [
   983      	{
   984        		"code": 10008,
   985        		"detail": "The request is semantically invalid: command presence",
   986        		"title": "CF-UnprocessableEntity"
   987      	},
   988  		{
   989  			"code": 10010,
   990        		"detail": "Organization not found",
   991        		"title": "CF-ResourceNotFound"
   992      	}
   993    	]
   994  }`
   995  				server.AppendHandlers(
   996  					CombineHandlers(
   997  						VerifyRequest(http.MethodDelete, "/v3/domains/some-domain-guid/relationships/shared_organizations/some-org-guid"),
   998  						RespondWith(http.StatusTeapot, response, http.Header{"X-Cf-Warnings": {"this is a warning"}}),
   999  					),
  1000  				)
  1001  			})
  1002  
  1003  			It("returns the error and all warnings", func() {
  1004  				Expect(executeErr).To(MatchError(ccerror.MultiError{
  1005  					ResponseCode: http.StatusTeapot,
  1006  					Errors: []ccerror.V3Error{
  1007  						{
  1008  							Code:   10008,
  1009  							Detail: "The request is semantically invalid: command presence",
  1010  							Title:  "CF-UnprocessableEntity",
  1011  						},
  1012  						{
  1013  							Code:   10010,
  1014  							Detail: "Organization not found",
  1015  							Title:  "CF-ResourceNotFound",
  1016  						},
  1017  					},
  1018  				}))
  1019  				Expect(warnings).To(ConsistOf("this is a warning"))
  1020  			})
  1021  		})
  1022  	})
  1023  })