github.com/mook-as/cf-cli@v7.0.0-beta.28.0.20200120190804-b91c115fae48+incompatible/cf/api/spaces/spaces_test.go (about)

     1  package spaces_test
     2  
     3  import (
     4  	"fmt"
     5  	"net/http"
     6  	"net/http/httptest"
     7  	"time"
     8  
     9  	"code.cloudfoundry.org/cli/cf/api/apifakes"
    10  	"code.cloudfoundry.org/cli/cf/errors"
    11  	"code.cloudfoundry.org/cli/cf/models"
    12  	"code.cloudfoundry.org/cli/cf/net"
    13  	"code.cloudfoundry.org/cli/cf/terminal/terminalfakes"
    14  	"code.cloudfoundry.org/cli/cf/trace/tracefakes"
    15  	testconfig "code.cloudfoundry.org/cli/cf/util/testhelpers/configuration"
    16  	testnet "code.cloudfoundry.org/cli/cf/util/testhelpers/net"
    17  
    18  	. "code.cloudfoundry.org/cli/cf/api/spaces"
    19  	. "code.cloudfoundry.org/cli/cf/util/testhelpers/matchers"
    20  	. "github.com/onsi/ginkgo"
    21  	. "github.com/onsi/gomega"
    22  	"github.com/onsi/gomega/ghttp"
    23  )
    24  
    25  var _ = Describe("Space Repository", func() {
    26  	Describe("ListSpaces", func() {
    27  		var (
    28  			ccServer *ghttp.Server
    29  			repo     CloudControllerSpaceRepository
    30  		)
    31  
    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 = NewCloudControllerSpaceRepository(configRepo, gateway)
    38  			ccServer.AppendHandlers(
    39  				ghttp.CombineHandlers(
    40  					ghttp.VerifyRequest("GET", "/v2/organizations/my-org-guid/spaces", "order-by=name&inline-relations-depth=1"),
    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/my-org-guid/spaces?order-by=name&page=2&inline-relations-depth=1",
    49  						"resources": [
    50  							{
    51  								"metadata": { "guid": "space3-guid" },
    52  								"entity": {
    53  								  "name": "Alpha",
    54  								  "allow_ssh": true,
    55  		              "security_groups": [
    56  		                {
    57  		                  "metadata": { "guid": "4302b3b4-4afc-4f12-ae6d-ed1bb815551f" },
    58  		                  "entity": { "name": "imma-security-group" }
    59  		                }
    60  		              ]
    61  		            }
    62  							},
    63  							{
    64  								"metadata": { "guid": "space2-guid" },
    65  								"entity": { "name": "Beta" }
    66  							}
    67  						]
    68  					}`),
    69  				),
    70  			)
    71  
    72  			ccServer.AppendHandlers(
    73  				ghttp.CombineHandlers(
    74  					ghttp.VerifyRequest("GET", "/v2/organizations/my-org-guid/spaces", "order-by=name&page=2&inline-relations-depth=1"),
    75  					ghttp.VerifyHeader(http.Header{
    76  						"accept": []string{"application/json"},
    77  					}),
    78  					ghttp.RespondWith(http.StatusOK, `{
    79  						"total_results": 3,
    80  						"total_pages": 2,
    81  						"prev_url": null,
    82  						"next_url": null,
    83  						"resources": [
    84  							{
    85  								"metadata": { "guid": "space1-guid" },
    86  								"entity": { "name": "Gamma" }
    87  							}
    88  						]
    89  					}`),
    90  				),
    91  			)
    92  		})
    93  
    94  		AfterEach(func() {
    95  			ccServer.Close()
    96  		})
    97  
    98  		It("lists all the spaces", func() {
    99  			spaces := []models.Space{}
   100  			apiErr := repo.ListSpaces(func(space models.Space) bool {
   101  				spaces = append(spaces, space)
   102  				return true
   103  			})
   104  
   105  			Expect(apiErr).NotTo(HaveOccurred())
   106  			Expect(len(spaces)).To(Equal(3))
   107  			Expect(spaces[0].GUID).To(Equal("space3-guid"))
   108  			Expect(spaces[0].AllowSSH).To(BeTrue())
   109  			Expect(spaces[0].SecurityGroups[0].Name).To(Equal("imma-security-group"))
   110  			Expect(spaces[0].Name).To(Equal("Alpha"))
   111  
   112  			Expect(spaces[1].GUID).To(Equal("space2-guid"))
   113  			Expect(spaces[1].Name).To(Equal("Beta"))
   114  
   115  			Expect(spaces[2].GUID).To(Equal("space1-guid"))
   116  			Expect(spaces[2].Name).To(Equal("Gamma"))
   117  		})
   118  	})
   119  
   120  	Describe("ListSpacesFromOrg", func() {
   121  		var (
   122  			ccServer *ghttp.Server
   123  			repo     CloudControllerSpaceRepository
   124  		)
   125  
   126  		BeforeEach(func() {
   127  			ccServer = ghttp.NewServer()
   128  			configRepo := testconfig.NewRepositoryWithDefaults()
   129  			configRepo.SetAPIEndpoint(ccServer.URL())
   130  			configRepo.SetOrganizationFields(models.OrganizationFields{})
   131  			gateway := net.NewCloudControllerGateway(configRepo, time.Now, new(terminalfakes.FakeUI), new(tracefakes.FakePrinter), "")
   132  			repo = NewCloudControllerSpaceRepository(configRepo, gateway)
   133  			ccServer.AppendHandlers(
   134  				ghttp.CombineHandlers(
   135  					ghttp.VerifyRequest("GET", "/v2/organizations/my-org-guid/spaces", "order-by=name&inline-relations-depth=1"),
   136  					ghttp.VerifyHeader(http.Header{
   137  						"accept": []string{"application/json"},
   138  					}),
   139  					ghttp.RespondWith(http.StatusOK, `{
   140  						"total_results": 3,
   141  						"total_pages": 2,
   142  						"prev_url": null,
   143  						"next_url": "/v2/organizations/my-org-guid/spaces?order-by=name&page=2&inline-relations-depth=1",
   144  						"resources": [
   145  							{
   146  								"metadata": { "guid": "space3-guid" },
   147  								"entity": {
   148  								  "name": "Alpha",
   149  								  "allow_ssh": true,
   150  		              "security_groups": [
   151  		                {
   152  		                  "metadata": { "guid": "4302b3b4-4afc-4f12-ae6d-ed1bb815551f" },
   153  		                  "entity": { "name": "imma-security-group" }
   154  		                }
   155  		              ]
   156  		            }
   157  							},
   158  							{
   159  								"metadata": { "guid": "space2-guid" },
   160  								"entity": { "name": "Beta" }
   161  							}
   162  						]
   163  					}`),
   164  				),
   165  			)
   166  
   167  			ccServer.AppendHandlers(
   168  				ghttp.CombineHandlers(
   169  					ghttp.VerifyRequest("GET", "/v2/organizations/my-org-guid/spaces", "order-by=name&page=2&inline-relations-depth=1"),
   170  					ghttp.VerifyHeader(http.Header{
   171  						"accept": []string{"application/json"},
   172  					}),
   173  					ghttp.RespondWith(http.StatusOK, `{
   174  						"total_results": 3,
   175  						"total_pages": 2,
   176  						"prev_url": null,
   177  						"next_url": null,
   178  						"resources": [
   179  							{
   180  								"metadata": { "guid": "space1-guid" },
   181  								"entity": { "name": "Gamma" }
   182  							}
   183  						]
   184  					}`),
   185  				),
   186  			)
   187  		})
   188  
   189  		AfterEach(func() {
   190  			ccServer.Close()
   191  		})
   192  
   193  		It("lists all the spaces", func() {
   194  			spaces := []models.Space{}
   195  			apiErr := repo.ListSpacesFromOrg("my-org-guid", func(space models.Space) bool {
   196  				spaces = append(spaces, space)
   197  				return true
   198  			})
   199  
   200  			Expect(apiErr).NotTo(HaveOccurred())
   201  			Expect(len(spaces)).To(Equal(3))
   202  			Expect(spaces[0].GUID).To(Equal("space3-guid"))
   203  			Expect(spaces[0].AllowSSH).To(BeTrue())
   204  			Expect(spaces[0].SecurityGroups[0].Name).To(Equal("imma-security-group"))
   205  			Expect(spaces[0].Name).To(Equal("Alpha"))
   206  
   207  			Expect(spaces[1].GUID).To(Equal("space2-guid"))
   208  			Expect(spaces[1].Name).To(Equal("Beta"))
   209  
   210  			Expect(spaces[2].GUID).To(Equal("space1-guid"))
   211  			Expect(spaces[2].Name).To(Equal("Gamma"))
   212  		})
   213  	})
   214  
   215  	Describe("finding spaces by name", func() {
   216  		It("returns the space", func() {
   217  			testSpacesFindByNameWithOrg("my-org-guid",
   218  				func(repo SpaceRepository, spaceName string) (models.Space, error) {
   219  					return repo.FindByName(spaceName)
   220  				},
   221  			)
   222  		})
   223  
   224  		It("can find spaces in a particular org", func() {
   225  			testSpacesFindByNameWithOrg("another-org-guid",
   226  				func(repo SpaceRepository, spaceName string) (models.Space, error) {
   227  					return repo.FindByNameInOrg(spaceName, "another-org-guid")
   228  				},
   229  			)
   230  		})
   231  
   232  		It("returns a 'not found' response when the space doesn't exist", func() {
   233  			testSpacesDidNotFindByNameWithOrg("my-org-guid",
   234  				func(repo SpaceRepository, spaceName string) (models.Space, error) {
   235  					return repo.FindByName(spaceName)
   236  				},
   237  			)
   238  		})
   239  
   240  		It("returns a 'not found' response when the space doesn't exist in the given org", func() {
   241  			testSpacesDidNotFindByNameWithOrg("another-org-guid",
   242  				func(repo SpaceRepository, spaceName string) (models.Space, error) {
   243  					return repo.FindByNameInOrg(spaceName, "another-org-guid")
   244  				},
   245  			)
   246  		})
   247  	})
   248  
   249  	It("creates spaces without a space-quota", func() {
   250  		request := apifakes.NewCloudControllerTestRequest(testnet.TestRequest{
   251  			Method:  "POST",
   252  			Path:    "/v2/spaces",
   253  			Matcher: testnet.RequestBodyMatcher(`{"name":"space-name","organization_guid":"my-org-guid"}`),
   254  			Response: testnet.TestResponse{Status: http.StatusCreated, Body: `
   255  			{
   256  				"metadata": {
   257  					"guid": "space-guid"
   258  				},
   259  				"entity": {
   260  					"name": "space-name"
   261  				}
   262  			}`},
   263  		})
   264  
   265  		ts, handler, repo := createSpacesRepo(request)
   266  		defer ts.Close()
   267  
   268  		space, apiErr := repo.Create("space-name", "my-org-guid", "")
   269  		Expect(handler).To(HaveAllRequestsCalled())
   270  		Expect(apiErr).NotTo(HaveOccurred())
   271  		Expect(space.GUID).To(Equal("space-guid"))
   272  		Expect(space.SpaceQuotaGUID).To(Equal(""))
   273  	})
   274  
   275  	It("creates spaces with a space-quota", func() {
   276  		request := apifakes.NewCloudControllerTestRequest(testnet.TestRequest{
   277  			Method:  "POST",
   278  			Path:    "/v2/spaces",
   279  			Matcher: testnet.RequestBodyMatcher(`{"name":"space-name","organization_guid":"my-org-guid","space_quota_definition_guid":"space-quota-guid"}`),
   280  			Response: testnet.TestResponse{Status: http.StatusCreated, Body: `
   281  			{
   282  				"metadata": {
   283  					"guid": "space-guid"
   284  				},
   285  				"entity": {
   286  					"name": "space-name",
   287  					"space_quota_definition_guid":"space-quota-guid"
   288  				}
   289  			}`},
   290  		})
   291  
   292  		ts, handler, repo := createSpacesRepo(request)
   293  		defer ts.Close()
   294  
   295  		space, apiErr := repo.Create("space-name", "my-org-guid", "space-quota-guid")
   296  		Expect(handler).To(HaveAllRequestsCalled())
   297  		Expect(apiErr).NotTo(HaveOccurred())
   298  		Expect(space.GUID).To(Equal("space-guid"))
   299  		Expect(space.SpaceQuotaGUID).To(Equal("space-quota-guid"))
   300  	})
   301  
   302  	It("sets allow_ssh field", func() {
   303  		request := apifakes.NewCloudControllerTestRequest(testnet.TestRequest{
   304  			Method:   "PUT",
   305  			Path:     "/v2/spaces/my-space-guid",
   306  			Matcher:  testnet.RequestBodyMatcher(`{"allow_ssh":true}`),
   307  			Response: testnet.TestResponse{Status: http.StatusCreated},
   308  		})
   309  
   310  		ts, handler, repo := createSpacesRepo(request)
   311  		defer ts.Close()
   312  
   313  		apiErr := repo.SetAllowSSH("my-space-guid", true)
   314  		Expect(handler).To(HaveAllRequestsCalled())
   315  		Expect(apiErr).NotTo(HaveOccurred())
   316  	})
   317  
   318  	It("renames spaces", func() {
   319  		request := apifakes.NewCloudControllerTestRequest(testnet.TestRequest{
   320  			Method:   "PUT",
   321  			Path:     "/v2/spaces/my-space-guid",
   322  			Matcher:  testnet.RequestBodyMatcher(`{"name":"new-space-name"}`),
   323  			Response: testnet.TestResponse{Status: http.StatusCreated},
   324  		})
   325  
   326  		ts, handler, repo := createSpacesRepo(request)
   327  		defer ts.Close()
   328  
   329  		apiErr := repo.Rename("my-space-guid", "new-space-name")
   330  		Expect(handler).To(HaveAllRequestsCalled())
   331  		Expect(apiErr).NotTo(HaveOccurred())
   332  	})
   333  
   334  	It("deletes spaces", func() {
   335  		request := apifakes.NewCloudControllerTestRequest(testnet.TestRequest{
   336  			Method:   "DELETE",
   337  			Path:     "/v2/spaces/my-space-guid?recursive=true",
   338  			Response: testnet.TestResponse{Status: http.StatusOK},
   339  		})
   340  
   341  		ts, handler, repo := createSpacesRepo(request)
   342  		defer ts.Close()
   343  
   344  		apiErr := repo.Delete("my-space-guid")
   345  		Expect(handler).To(HaveAllRequestsCalled())
   346  		Expect(apiErr).NotTo(HaveOccurred())
   347  	})
   348  })
   349  
   350  func testSpacesFindByNameWithOrg(orgGUID string, findByName func(SpaceRepository, string) (models.Space, error)) {
   351  	findSpaceByNameResponse := testnet.TestResponse{
   352  		Status: http.StatusOK,
   353  		Body: `
   354  {
   355    "resources": [
   356      {
   357        "metadata": {
   358          "guid": "space1-guid"
   359        },
   360        "entity": {
   361          "name": "Space1",
   362          "organization_guid": "org1-guid",
   363          "organization": {
   364            "metadata": {
   365              "guid": "org1-guid"
   366            },
   367            "entity": {
   368              "name": "Org1"
   369            }
   370          },
   371          "apps": [
   372            {
   373              "metadata": {
   374                "guid": "app1-guid"
   375              },
   376              "entity": {
   377                "name": "app1"
   378              }
   379            },
   380            {
   381              "metadata": {
   382                "guid": "app2-guid"
   383              },
   384              "entity": {
   385                "name": "app2"
   386              }
   387            }
   388          ],
   389          "domains": [
   390            {
   391              "metadata": {
   392                "guid": "domain1-guid"
   393              },
   394              "entity": {
   395                "name": "domain1"
   396              }
   397            }
   398          ],
   399          "service_instances": [
   400            {
   401  			"metadata": {
   402                "guid": "service1-guid"
   403              },
   404              "entity": {
   405                "name": "service1"
   406              }
   407            }
   408          ]
   409        }
   410      }
   411    ]
   412  }`}
   413  	request := apifakes.NewCloudControllerTestRequest(testnet.TestRequest{
   414  		Method:   "GET",
   415  		Path:     fmt.Sprintf("/v2/organizations/%s/spaces?q=name%%3Aspace1", orgGUID),
   416  		Response: findSpaceByNameResponse,
   417  	})
   418  
   419  	ts, handler, repo := createSpacesRepo(request)
   420  	defer ts.Close()
   421  
   422  	space, apiErr := findByName(repo, "Space1")
   423  	Expect(handler).To(HaveAllRequestsCalled())
   424  	Expect(apiErr).NotTo(HaveOccurred())
   425  	Expect(space.Name).To(Equal("Space1"))
   426  	Expect(space.GUID).To(Equal("space1-guid"))
   427  
   428  	Expect(space.Organization.GUID).To(Equal("org1-guid"))
   429  
   430  	Expect(len(space.Applications)).To(Equal(2))
   431  	Expect(space.Applications[0].GUID).To(Equal("app1-guid"))
   432  	Expect(space.Applications[1].GUID).To(Equal("app2-guid"))
   433  
   434  	Expect(len(space.Domains)).To(Equal(1))
   435  	Expect(space.Domains[0].GUID).To(Equal("domain1-guid"))
   436  
   437  	Expect(len(space.ServiceInstances)).To(Equal(1))
   438  	Expect(space.ServiceInstances[0].GUID).To(Equal("service1-guid"))
   439  
   440  	Expect(apiErr).NotTo(HaveOccurred())
   441  	return
   442  }
   443  
   444  func testSpacesDidNotFindByNameWithOrg(orgGUID string, findByName func(SpaceRepository, string) (models.Space, error)) {
   445  	request := apifakes.NewCloudControllerTestRequest(testnet.TestRequest{
   446  		Method: "GET",
   447  		Path:   fmt.Sprintf("/v2/organizations/%s/spaces?q=name%%3Aspace1", orgGUID),
   448  		Response: testnet.TestResponse{
   449  			Status: http.StatusOK,
   450  			Body:   ` { "resources": [ ] }`,
   451  		},
   452  	})
   453  
   454  	ts, handler, repo := createSpacesRepo(request)
   455  	defer ts.Close()
   456  
   457  	_, apiErr := findByName(repo, "Space1")
   458  	Expect(handler).To(HaveAllRequestsCalled())
   459  
   460  	Expect(apiErr.(*errors.ModelNotFoundError)).NotTo(BeNil())
   461  }
   462  
   463  func createSpacesRepo(reqs ...testnet.TestRequest) (ts *httptest.Server, handler *testnet.TestHandler, repo SpaceRepository) {
   464  	ts, handler = testnet.NewServer(reqs)
   465  	configRepo := testconfig.NewRepositoryWithDefaults()
   466  	configRepo.SetAPIEndpoint(ts.URL)
   467  	gateway := net.NewCloudControllerGateway(configRepo, time.Now, new(terminalfakes.FakeUI), new(tracefakes.FakePrinter), "")
   468  	repo = NewCloudControllerSpaceRepository(configRepo, gateway)
   469  	return
   470  }