github.com/dcarley/cf-cli@v6.24.1-0.20170220111324-4225ff346898+incompatible/cf/api/organizations/organizations_test.go (about)

     1  package organizations_test
     2  
     3  import (
     4  	"net/http"
     5  	"net/http/httptest"
     6  	"time"
     7  
     8  	"code.cloudfoundry.org/cli/cf/api/apifakes"
     9  	"code.cloudfoundry.org/cli/cf/errors"
    10  	"code.cloudfoundry.org/cli/cf/models"
    11  	"code.cloudfoundry.org/cli/cf/net"
    12  	"code.cloudfoundry.org/cli/cf/terminal/terminalfakes"
    13  	testconfig "code.cloudfoundry.org/cli/util/testhelpers/configuration"
    14  	testnet "code.cloudfoundry.org/cli/util/testhelpers/net"
    15  
    16  	. "code.cloudfoundry.org/cli/cf/api/organizations"
    17  	"code.cloudfoundry.org/cli/cf/trace/tracefakes"
    18  	. "code.cloudfoundry.org/cli/util/testhelpers/matchers"
    19  	. "github.com/onsi/ginkgo"
    20  	. "github.com/onsi/gomega"
    21  	"github.com/onsi/gomega/ghttp"
    22  )
    23  
    24  var _ = Describe("Organization Repository", func() {
    25  	Describe("ListOrgs", func() {
    26  		var (
    27  			ccServer *ghttp.Server
    28  			repo     CloudControllerOrganizationRepository
    29  		)
    30  
    31  		Context("when there are orgs", func() {
    32  			BeforeEach(func() {
    33  				ccServer = ghttp.NewServer()
    34  				configRepo := testconfig.NewRepositoryWithDefaults()
    35  				configRepo.SetAPIEndpoint(ccServer.URL())
    36  				gateway := net.NewCloudControllerGateway(configRepo, time.Now, new(terminalfakes.FakeUI), new(tracefakes.FakePrinter), "")
    37  				repo = NewCloudControllerOrganizationRepository(configRepo, gateway)
    38  				ccServer.AppendHandlers(
    39  					ghttp.CombineHandlers(
    40  						ghttp.VerifyRequest("GET", "/v2/organizations", "order-by=name"),
    41  						ghttp.VerifyHeader(http.Header{
    42  							"accept": []string{"application/json"},
    43  						}),
    44  						ghttp.RespondWith(http.StatusOK, `{
    45  						"total_results": 3,
    46  						"total_pages": 2,
    47  						"prev_url": null,
    48  						"next_url": "/v2/organizations?order-by=name&page=2",
    49  						"resources": [
    50  							{
    51  								"metadata": { "guid": "org3-guid" },
    52  								"entity": { "name": "Alpha" }
    53  							},
    54  							{
    55  								"metadata": { "guid": "org2-guid" },
    56  								"entity": { "name": "Beta" }
    57  							}
    58  						]
    59  					}`),
    60  					),
    61  				)
    62  
    63  				ccServer.AppendHandlers(
    64  					ghttp.CombineHandlers(
    65  						ghttp.VerifyRequest("GET", "/v2/organizations", "order-by=name&page=2"),
    66  						ghttp.VerifyHeader(http.Header{
    67  							"accept": []string{"application/json"},
    68  						}),
    69  						ghttp.RespondWith(http.StatusOK, `{
    70  						"total_results": 3,
    71  						"total_pages": 2,
    72  						"prev_url": null,
    73  						"next_url": null,
    74  						"resources": [
    75  							{
    76  								"metadata": { "guid": "org1-guid" },
    77  								"entity": { "name": "Gamma" }
    78  							}
    79  						]
    80  					}`),
    81  					),
    82  				)
    83  			})
    84  
    85  			AfterEach(func() {
    86  				ccServer.Close()
    87  			})
    88  
    89  			Context("when given a non-zero positive limit", func() {
    90  				It("should return no more than the limit number of organizations", func() {
    91  					orgs, err := repo.ListOrgs(2)
    92  					Expect(err).NotTo(HaveOccurred())
    93  					Expect(len(orgs)).To(Equal(2))
    94  				})
    95  
    96  				It("should not make more requests than necessary to retrieve the requested number of orgs", func() {
    97  					_, err := repo.ListOrgs(2)
    98  					Expect(err).NotTo(HaveOccurred())
    99  					Expect(ccServer.ReceivedRequests()).Should(HaveLen(1))
   100  				})
   101  			})
   102  
   103  			Context("when given a zero limit", func() {
   104  				It("should return all organizations", func() {
   105  					orgs, err := repo.ListOrgs(0)
   106  					Expect(err).NotTo(HaveOccurred())
   107  					Expect(len(orgs)).To(Equal(3))
   108  				})
   109  
   110  				It("lists the orgs from the the /v2/orgs endpoint in alphabetical order", func() {
   111  					orgs, apiErr := repo.ListOrgs(0)
   112  
   113  					Expect(len(orgs)).To(Equal(3))
   114  					Expect(orgs[0].GUID).To(Equal("org3-guid"))
   115  					Expect(orgs[1].GUID).To(Equal("org2-guid"))
   116  					Expect(orgs[2].GUID).To(Equal("org1-guid"))
   117  
   118  					Expect(orgs[0].Name).To(Equal("Alpha"))
   119  					Expect(orgs[1].Name).To(Equal("Beta"))
   120  					Expect(orgs[2].Name).To(Equal("Gamma"))
   121  					Expect(apiErr).NotTo(HaveOccurred())
   122  				})
   123  			})
   124  		})
   125  
   126  		Context("when there are no orgs", func() {
   127  			BeforeEach(func() {
   128  				ccServer = ghttp.NewServer()
   129  				configRepo := testconfig.NewRepositoryWithDefaults()
   130  				configRepo.SetAPIEndpoint(ccServer.URL())
   131  				gateway := net.NewCloudControllerGateway(configRepo, time.Now, new(terminalfakes.FakeUI), new(tracefakes.FakePrinter), "")
   132  				repo = NewCloudControllerOrganizationRepository(configRepo, gateway)
   133  				ccServer.AppendHandlers(
   134  					ghttp.CombineHandlers(
   135  						ghttp.VerifyRequest("GET", "/v2/organizations"),
   136  						ghttp.VerifyHeader(http.Header{
   137  							"accept": []string{"application/json"},
   138  						}),
   139  						ghttp.RespondWith(http.StatusOK, `{"resources": []}`),
   140  					),
   141  				)
   142  			})
   143  
   144  			AfterEach(func() {
   145  				ccServer.Close()
   146  			})
   147  
   148  			It("does not call the provided function", func() {
   149  				_, apiErr := repo.ListOrgs(0)
   150  
   151  				Expect(apiErr).NotTo(HaveOccurred())
   152  			})
   153  		})
   154  	})
   155  
   156  	Describe(".GetManyOrgsByGUID", func() {
   157  		It("requests each org", func() {
   158  			firstOrgRequest := apifakes.NewCloudControllerTestRequest(testnet.TestRequest{
   159  				Method: "GET",
   160  				Path:   "/v2/organizations/org1-guid",
   161  				Response: testnet.TestResponse{Status: http.StatusOK, Body: `{
   162  		  "metadata": { "guid": "org1-guid" },
   163  		  "entity": { "name": "Org1" }
   164  		}`},
   165  			})
   166  			secondOrgRequest := apifakes.NewCloudControllerTestRequest(testnet.TestRequest{
   167  				Method: "GET",
   168  				Path:   "/v2/organizations/org2-guid",
   169  				Response: testnet.TestResponse{Status: http.StatusOK, Body: `{
   170  			"metadata": { "guid": "org2-guid" },
   171  		  "entity": { "name": "Org2" }
   172  	  }`},
   173  			})
   174  			testserver, handler, repo := createOrganizationRepo(firstOrgRequest, secondOrgRequest)
   175  			defer testserver.Close()
   176  
   177  			orgGUIDs := []string{"org1-guid", "org2-guid"}
   178  			orgs, err := repo.GetManyOrgsByGUID(orgGUIDs)
   179  			Expect(err).NotTo(HaveOccurred())
   180  
   181  			Expect(handler).To(HaveAllRequestsCalled())
   182  			Expect(len(orgs)).To(Equal(2))
   183  			Expect(orgs[0].GUID).To(Equal("org1-guid"))
   184  			Expect(orgs[1].GUID).To(Equal("org2-guid"))
   185  		})
   186  	})
   187  
   188  	Describe("finding organizations by name", func() {
   189  		It("returns the org with that name", func() {
   190  			req := apifakes.NewCloudControllerTestRequest(testnet.TestRequest{
   191  				Method: "GET",
   192  				Path:   "/v2/organizations?q=name%3Aorg1&inline-relations-depth=1",
   193  				Response: testnet.TestResponse{Status: http.StatusOK, Body: `{"resources": [{
   194  	  "metadata": { "guid": "org1-guid" },
   195  	  "entity": {
   196  		"name": "Org1",
   197  		"quota_definition": {
   198  		  "entity": {
   199  			"name": "not-your-average-quota",
   200  			"memory_limit": 128
   201  		  }
   202  		},
   203  		"spaces": [{
   204  		  "metadata": { "guid": "space1-guid" },
   205  		  "entity": { "name": "Space1" }
   206  		}],
   207  		"domains": [{
   208  		  "metadata": { "guid": "domain1-guid" },
   209  		  "entity": { "name": "cfapps.io" }
   210  		}],
   211  		"space_quota_definitions":[{
   212  			"metadata": {"guid": "space-quota1-guid"},
   213  			"entity": {"name": "space-quota1"}
   214  		}]
   215  	  }
   216  	}]}`},
   217  			})
   218  
   219  			testserver, handler, repo := createOrganizationRepo(req)
   220  			defer testserver.Close()
   221  			existingOrg := models.Organization{}
   222  			existingOrg.GUID = "org1-guid"
   223  			existingOrg.Name = "Org1"
   224  
   225  			org, apiErr := repo.FindByName("Org1")
   226  			Expect(handler).To(HaveAllRequestsCalled())
   227  			Expect(apiErr).NotTo(HaveOccurred())
   228  
   229  			Expect(org.Name).To(Equal(existingOrg.Name))
   230  			Expect(org.GUID).To(Equal(existingOrg.GUID))
   231  			Expect(org.QuotaDefinition.Name).To(Equal("not-your-average-quota"))
   232  			Expect(org.QuotaDefinition.MemoryLimit).To(Equal(int64(128)))
   233  			Expect(len(org.Spaces)).To(Equal(1))
   234  			Expect(org.Spaces[0].Name).To(Equal("Space1"))
   235  			Expect(org.Spaces[0].GUID).To(Equal("space1-guid"))
   236  			Expect(len(org.Domains)).To(Equal(1))
   237  			Expect(org.Domains[0].Name).To(Equal("cfapps.io"))
   238  			Expect(org.Domains[0].GUID).To(Equal("domain1-guid"))
   239  			Expect(len(org.SpaceQuotas)).To(Equal(1))
   240  			Expect(org.SpaceQuotas[0].Name).To(Equal("space-quota1"))
   241  			Expect(org.SpaceQuotas[0].GUID).To(Equal("space-quota1-guid"))
   242  		})
   243  
   244  		It("returns a ModelNotFoundError when the org cannot be found", func() {
   245  			req := apifakes.NewCloudControllerTestRequest(testnet.TestRequest{
   246  				Method:   "GET",
   247  				Path:     "/v2/organizations?q=name%3Aorg1&inline-relations-depth=1",
   248  				Response: testnet.TestResponse{Status: http.StatusOK, Body: `{"resources": []}`},
   249  			})
   250  
   251  			testserver, handler, repo := createOrganizationRepo(req)
   252  			defer testserver.Close()
   253  
   254  			_, apiErr := repo.FindByName("org1")
   255  			Expect(handler).To(HaveAllRequestsCalled())
   256  			Expect(apiErr.(*errors.ModelNotFoundError)).NotTo(BeNil())
   257  		})
   258  
   259  		It("returns an api error when the response is not successful", func() {
   260  			requestHandler := apifakes.NewCloudControllerTestRequest(testnet.TestRequest{
   261  				Method:   "GET",
   262  				Path:     "/v2/organizations?q=name%3Aorg1&inline-relations-depth=1",
   263  				Response: testnet.TestResponse{Status: http.StatusBadGateway, Body: `{"resources": []}`},
   264  			})
   265  
   266  			testserver, handler, repo := createOrganizationRepo(requestHandler)
   267  			defer testserver.Close()
   268  
   269  			_, apiErr := repo.FindByName("org1")
   270  			_, ok := apiErr.(*errors.ModelNotFoundError)
   271  			Expect(ok).To(BeFalse())
   272  			Expect(handler).To(HaveAllRequestsCalled())
   273  		})
   274  	})
   275  
   276  	Describe(".Create", func() {
   277  		It("creates the org and sends only the org name if the quota flag is not provided", func() {
   278  			org := models.Organization{
   279  				OrganizationFields: models.OrganizationFields{
   280  					Name: "my-org",
   281  				}}
   282  
   283  			req := apifakes.NewCloudControllerTestRequest(testnet.TestRequest{
   284  				Method:   "POST",
   285  				Path:     "/v2/organizations",
   286  				Matcher:  testnet.RequestBodyMatcher(`{"name":"my-org"}`),
   287  				Response: testnet.TestResponse{Status: http.StatusCreated},
   288  			})
   289  
   290  			testserver, handler, repo := createOrganizationRepo(req)
   291  			defer testserver.Close()
   292  
   293  			apiErr := repo.Create(org)
   294  			Expect(handler).To(HaveAllRequestsCalled())
   295  			Expect(apiErr).NotTo(HaveOccurred())
   296  		})
   297  
   298  		It("creates the org with the provided quota", func() {
   299  			org := models.Organization{
   300  				OrganizationFields: models.OrganizationFields{
   301  					Name: "my-org",
   302  					QuotaDefinition: models.QuotaFields{
   303  						GUID: "my-quota-guid",
   304  					},
   305  				}}
   306  
   307  			req := apifakes.NewCloudControllerTestRequest(testnet.TestRequest{
   308  				Method:   "POST",
   309  				Path:     "/v2/organizations",
   310  				Matcher:  testnet.RequestBodyMatcher(`{"name":"my-org", "quota_definition_guid":"my-quota-guid"}`),
   311  				Response: testnet.TestResponse{Status: http.StatusCreated},
   312  			})
   313  
   314  			testserver, handler, repo := createOrganizationRepo(req)
   315  			defer testserver.Close()
   316  
   317  			apiErr := repo.Create(org)
   318  			Expect(handler).To(HaveAllRequestsCalled())
   319  			Expect(apiErr).NotTo(HaveOccurred())
   320  		})
   321  	})
   322  
   323  	Describe("renaming orgs", func() {
   324  		It("renames the org with the given guid", func() {
   325  			req := apifakes.NewCloudControllerTestRequest(testnet.TestRequest{
   326  				Method:   "PUT",
   327  				Path:     "/v2/organizations/my-org-guid",
   328  				Matcher:  testnet.RequestBodyMatcher(`{"name":"my-new-org"}`),
   329  				Response: testnet.TestResponse{Status: http.StatusCreated},
   330  			})
   331  
   332  			testserver, handler, repo := createOrganizationRepo(req)
   333  			defer testserver.Close()
   334  
   335  			apiErr := repo.Rename("my-org-guid", "my-new-org")
   336  			Expect(handler).To(HaveAllRequestsCalled())
   337  			Expect(apiErr).NotTo(HaveOccurred())
   338  		})
   339  	})
   340  
   341  	Describe("deleting orgs", func() {
   342  		It("deletes the org with the given guid", func() {
   343  			req := apifakes.NewCloudControllerTestRequest(testnet.TestRequest{
   344  				Method:   "DELETE",
   345  				Path:     "/v2/organizations/my-org-guid?recursive=true",
   346  				Response: testnet.TestResponse{Status: http.StatusOK},
   347  			})
   348  
   349  			testserver, handler, repo := createOrganizationRepo(req)
   350  			defer testserver.Close()
   351  
   352  			apiErr := repo.Delete("my-org-guid")
   353  			Expect(handler).To(HaveAllRequestsCalled())
   354  			Expect(apiErr).NotTo(HaveOccurred())
   355  		})
   356  	})
   357  
   358  	Describe("SharePrivateDomain", func() {
   359  		It("shares the private domain with the given org", func() {
   360  			req := apifakes.NewCloudControllerTestRequest(testnet.TestRequest{
   361  				Method:   "PUT",
   362  				Path:     "/v2/organizations/my-org-guid/private_domains/domain-guid",
   363  				Response: testnet.TestResponse{Status: http.StatusOK},
   364  			})
   365  
   366  			testserver, handler, repo := createOrganizationRepo(req)
   367  			defer testserver.Close()
   368  
   369  			apiErr := repo.SharePrivateDomain("my-org-guid", "domain-guid")
   370  			Expect(handler).To(HaveAllRequestsCalled())
   371  			Expect(apiErr).NotTo(HaveOccurred())
   372  		})
   373  	})
   374  
   375  	Describe("UnsharePrivateDomain", func() {
   376  		It("unshares the private domain with the given org", func() {
   377  			req := apifakes.NewCloudControllerTestRequest(testnet.TestRequest{
   378  				Method:   "DELETE",
   379  				Path:     "/v2/organizations/my-org-guid/private_domains/domain-guid",
   380  				Response: testnet.TestResponse{Status: http.StatusOK},
   381  			})
   382  
   383  			testserver, handler, repo := createOrganizationRepo(req)
   384  			defer testserver.Close()
   385  
   386  			apiErr := repo.UnsharePrivateDomain("my-org-guid", "domain-guid")
   387  			Expect(handler).To(HaveAllRequestsCalled())
   388  			Expect(apiErr).NotTo(HaveOccurred())
   389  		})
   390  	})
   391  })
   392  
   393  func createOrganizationRepo(reqs ...testnet.TestRequest) (testserver *httptest.Server, handler *testnet.TestHandler, repo OrganizationRepository) {
   394  	testserver, handler = testnet.NewServer(reqs)
   395  
   396  	configRepo := testconfig.NewRepositoryWithDefaults()
   397  	configRepo.SetAPIEndpoint(testserver.URL)
   398  	gateway := net.NewCloudControllerGateway(configRepo, time.Now, new(terminalfakes.FakeUI), new(tracefakes.FakePrinter), "")
   399  	repo = NewCloudControllerOrganizationRepository(configRepo, gateway)
   400  	return
   401  }