github.com/cloudfoundry/cli@v7.1.0+incompatible/cf/api/buildpacks_test.go (about)

     1  package api_test
     2  
     3  import (
     4  	"net/http"
     5  	"net/http/httptest"
     6  	"time"
     7  
     8  	. "code.cloudfoundry.org/cli/cf/api"
     9  	"code.cloudfoundry.org/cli/cf/api/apifakes"
    10  	"code.cloudfoundry.org/cli/cf/configuration/coreconfig"
    11  	"code.cloudfoundry.org/cli/cf/errors"
    12  	"code.cloudfoundry.org/cli/cf/models"
    13  	"code.cloudfoundry.org/cli/cf/net"
    14  	"code.cloudfoundry.org/cli/cf/terminal/terminalfakes"
    15  	"code.cloudfoundry.org/cli/cf/trace/tracefakes"
    16  	testconfig "code.cloudfoundry.org/cli/cf/util/testhelpers/configuration"
    17  	. "code.cloudfoundry.org/cli/cf/util/testhelpers/matchers"
    18  	testnet "code.cloudfoundry.org/cli/cf/util/testhelpers/net"
    19  	. "github.com/onsi/ginkgo"
    20  	. "github.com/onsi/gomega"
    21  )
    22  
    23  var _ = Describe("Buildpacks repo", func() {
    24  	var (
    25  		ts      *httptest.Server
    26  		handler *testnet.TestHandler
    27  		config  coreconfig.ReadWriter
    28  		repo    BuildpackRepository
    29  	)
    30  
    31  	BeforeEach(func() {
    32  		config = testconfig.NewRepositoryWithDefaults()
    33  		gateway := net.NewCloudControllerGateway(config, time.Now, new(terminalfakes.FakeUI), new(tracefakes.FakePrinter), "")
    34  		repo = NewCloudControllerBuildpackRepository(config, gateway)
    35  	})
    36  
    37  	AfterEach(func() {
    38  		ts.Close()
    39  	})
    40  
    41  	var setupTestServer = func(requests ...testnet.TestRequest) {
    42  		ts, handler = testnet.NewServer(requests)
    43  		config.SetAPIEndpoint(ts.URL)
    44  	}
    45  
    46  	It("lists buildpacks", func() {
    47  		setupTestServer(
    48  			apifakes.NewCloudControllerTestRequest(testnet.TestRequest{
    49  				Method: "GET",
    50  				Path:   "/v2/buildpacks",
    51  				Response: testnet.TestResponse{
    52  					Status: http.StatusOK,
    53  					Body: `{
    54  					  "next_url": "/v2/buildpacks?page=2",
    55  					  "resources": [
    56  						{
    57  						  "metadata": {
    58  							"guid": "buildpack1-guid"
    59  						  },
    60  						  "entity": {
    61  							"name": "Buildpack1",
    62  							"position" : 1,
    63  							"filename" : "firstbp.zip"
    64  						  }
    65  						}
    66  					  ]
    67  					}`}}),
    68  			apifakes.NewCloudControllerTestRequest(testnet.TestRequest{
    69  				Method: "GET",
    70  				Path:   "/v2/buildpacks?page=2",
    71  				Response: testnet.TestResponse{
    72  					Status: http.StatusOK,
    73  					Body: `{
    74  					  "resources": [
    75  						{
    76  						  "metadata": {
    77  							"guid": "buildpack2-guid"
    78  						  },
    79  						  "entity": {
    80  							"name": "Buildpack2",
    81  							"position" : 2
    82  						  }
    83  						}
    84  					  ]
    85  					}`},
    86  			}))
    87  
    88  		buildpacks := []models.Buildpack{}
    89  		err := repo.ListBuildpacks(func(b models.Buildpack) bool {
    90  			buildpacks = append(buildpacks, b)
    91  			return true
    92  		})
    93  
    94  		one := 1
    95  		two := 2
    96  		Expect(buildpacks).To(ConsistOf([]models.Buildpack{
    97  			{
    98  				GUID:     "buildpack1-guid",
    99  				Name:     "Buildpack1",
   100  				Position: &one,
   101  				Filename: "firstbp.zip",
   102  			},
   103  			{
   104  				GUID:     "buildpack2-guid",
   105  				Name:     "Buildpack2",
   106  				Position: &two,
   107  			},
   108  		}))
   109  		Expect(handler).To(HaveAllRequestsCalled())
   110  		Expect(err).NotTo(HaveOccurred())
   111  	})
   112  
   113  	Describe("finding buildpacks by name", func() {
   114  		It("returns the buildpack with that name", func() {
   115  			setupTestServer(apifakes.NewCloudControllerTestRequest(testnet.TestRequest{
   116  				Method: "GET",
   117  				Path:   "/v2/buildpacks?q=name%3ABuildpack1",
   118  				Response: testnet.TestResponse{
   119  					Status: http.StatusOK,
   120  					Body: `{"resources": [
   121  					  {
   122  						  "metadata": {
   123  							  "guid": "buildpack1-guid"
   124  						  },
   125  						  "entity": {
   126  							  "name": "Buildpack1",
   127  							  "position": 10
   128  						  }
   129  					  }
   130  					  ]
   131  				  }`}}))
   132  
   133  			buildpack, apiErr := repo.FindByName("Buildpack1")
   134  
   135  			Expect(handler).To(HaveAllRequestsCalled())
   136  			Expect(apiErr).NotTo(HaveOccurred())
   137  
   138  			Expect(buildpack.Name).To(Equal("Buildpack1"))
   139  			Expect(buildpack.GUID).To(Equal("buildpack1-guid"))
   140  			Expect(*buildpack.Position).To(Equal(10))
   141  		})
   142  
   143  		It("returns a ModelNotFoundError when the buildpack is not found", func() {
   144  			setupTestServer(apifakes.NewCloudControllerTestRequest(testnet.TestRequest{
   145  				Method: "GET",
   146  				Path:   "/v2/buildpacks?q=name%3ABuildpack1",
   147  				Response: testnet.TestResponse{
   148  					Status: http.StatusOK,
   149  					Body:   `{"resources": []}`,
   150  				},
   151  			}))
   152  
   153  			_, apiErr := repo.FindByName("Buildpack1")
   154  			Expect(handler).To(HaveAllRequestsCalled())
   155  			Expect(apiErr.(*errors.ModelNotFoundError)).NotTo(BeNil())
   156  		})
   157  
   158  		It("returns a AmbiguousModelError when more than one buildpack with the same name exists", func() {
   159  			setupTestServer(apifakes.NewCloudControllerTestRequest(testnet.TestRequest{
   160  				Method: "GET",
   161  				Path:   "/v2/buildpacks?q=name%3ABuildpack1",
   162  				Response: testnet.TestResponse{
   163  					Status: http.StatusOK,
   164  					Body: `{"resources": [
   165  					  {
   166  						  "metadata": {
   167  							  "guid": "buildpack1-guid"
   168  						  },
   169  						  "entity": {
   170  							  "name": "Buildpack1",
   171  								"stack": "Stack1",
   172  							  "position": 10
   173  						  }
   174  					  },
   175  					  {
   176  						  "metadata": {
   177  							  "guid": "buildpack1-guid2"
   178  						  },
   179  						  "entity": {
   180  							  "name": "Buildpack1",
   181  								"stack": "Stack2",
   182  							  "position": 11
   183  						  }
   184  					  }
   185  					  ]
   186  				  }`},
   187  			}))
   188  
   189  			_, apiErr := repo.FindByName("Buildpack1")
   190  			Expect(handler).To(HaveAllRequestsCalled())
   191  			Expect(apiErr).To(BeAssignableToTypeOf(&errors.AmbiguousModelError{}))
   192  		})
   193  	})
   194  
   195  	Describe("finding buildpacks by name and stack", func() {
   196  		It("returns the buildpack with that name and stack", func() {
   197  			setupTestServer(apifakes.NewCloudControllerTestRequest(testnet.TestRequest{
   198  				Method: "GET",
   199  				Path:   "/v2/buildpacks?q=name%3ABuildpack1%3Bstack%3AStack1",
   200  				Response: testnet.TestResponse{
   201  					Status: http.StatusOK,
   202  					Body: `{"resources": [
   203  					  {
   204  						  "metadata": {
   205  							  "guid": "buildpack1-guid"
   206  						  },
   207  						  "entity": {
   208  							  "name": "Buildpack1",
   209  								"stack": "Stack1",
   210  							  "position": 10
   211  						  }
   212  					  }
   213  					  ]
   214  				  }`}}))
   215  
   216  			buildpack, apiErr := repo.FindByNameAndStack("Buildpack1", "Stack1")
   217  
   218  			Expect(handler).To(HaveAllRequestsCalled())
   219  			Expect(apiErr).NotTo(HaveOccurred())
   220  
   221  			Expect(buildpack.Name).To(Equal("Buildpack1"))
   222  			Expect(buildpack.Stack).To(Equal("Stack1"))
   223  			Expect(buildpack.GUID).To(Equal("buildpack1-guid"))
   224  			Expect(*buildpack.Position).To(Equal(10))
   225  		})
   226  
   227  		It("returns a ModelNotFoundError when the buildpack is not found", func() {
   228  			setupTestServer(apifakes.NewCloudControllerTestRequest(testnet.TestRequest{
   229  				Method: "GET",
   230  				Path:   "/v2/buildpacks?q=name%3ABuildpack1%3Bstack%3AStack1",
   231  				Response: testnet.TestResponse{
   232  					Status: http.StatusOK,
   233  					Body:   `{"resources": []}`,
   234  				},
   235  			}))
   236  
   237  			_, apiErr := repo.FindByNameAndStack("Buildpack1", "Stack1")
   238  			Expect(handler).To(HaveAllRequestsCalled())
   239  			Expect(apiErr.(*errors.ModelNotFoundError)).NotTo(BeNil())
   240  		})
   241  	})
   242  
   243  	Describe("creating buildpacks", func() {
   244  		It("returns an error when the buildpack has an invalid name", func() {
   245  			setupTestServer(testnet.TestRequest{
   246  				Method: "POST",
   247  				Path:   "/v2/buildpacks",
   248  				Response: testnet.TestResponse{
   249  					Status: http.StatusBadRequest,
   250  					Body: `{
   251  					"code":290003,
   252  					"description":"Buildpack is invalid: [\"name can only contain alphanumeric characters\"]",
   253  					"error_code":"CF-BuildpackInvalid"
   254  				}`,
   255  				}})
   256  
   257  			one := 1
   258  			createdBuildpack, apiErr := repo.Create("name with space", &one, nil, nil)
   259  			Expect(apiErr).To(HaveOccurred())
   260  			Expect(createdBuildpack).To(Equal(models.Buildpack{}))
   261  			Expect(apiErr.(errors.HTTPError).ErrorCode()).To(Equal("290003"))
   262  			Expect(apiErr.Error()).To(ContainSubstring("Buildpack is invalid"))
   263  		})
   264  
   265  		It("sets the position flag when creating a buildpack", func() {
   266  			setupTestServer(apifakes.NewCloudControllerTestRequest(testnet.TestRequest{
   267  				Method:  "POST",
   268  				Path:    "/v2/buildpacks",
   269  				Matcher: testnet.RequestBodyMatcher(`{"name":"my-cool-buildpack","position":999}`),
   270  				Response: testnet.TestResponse{
   271  					Status: http.StatusCreated,
   272  					Body: `{
   273  					"metadata": {
   274  						"guid": "my-cool-buildpack-guid"
   275  					},
   276  					"entity": {
   277  						"name": "my-cool-buildpack",
   278  						"position":999
   279  					}
   280  				}`},
   281  			}))
   282  
   283  			position := 999
   284  			created, apiErr := repo.Create("my-cool-buildpack", &position, nil, nil)
   285  
   286  			Expect(handler).To(HaveAllRequestsCalled())
   287  			Expect(apiErr).NotTo(HaveOccurred())
   288  
   289  			Expect(created.GUID).NotTo(BeNil())
   290  			Expect("my-cool-buildpack").To(Equal(created.Name))
   291  			Expect(999).To(Equal(*created.Position))
   292  		})
   293  
   294  		It("sets the enabled flag when creating a buildpack", func() {
   295  			setupTestServer(apifakes.NewCloudControllerTestRequest(testnet.TestRequest{
   296  				Method:  "POST",
   297  				Path:    "/v2/buildpacks",
   298  				Matcher: testnet.RequestBodyMatcher(`{"name":"my-cool-buildpack","position":999, "enabled":true}`),
   299  				Response: testnet.TestResponse{
   300  					Status: http.StatusCreated,
   301  					Body: `{
   302  					"metadata": {
   303  						"guid": "my-cool-buildpack-guid"
   304  					},
   305  					"entity": {
   306  						"name": "my-cool-buildpack",
   307  						"position":999,
   308  						"enabled":true
   309  					}
   310  				}`},
   311  			}))
   312  
   313  			position := 999
   314  			enabled := true
   315  			created, apiErr := repo.Create("my-cool-buildpack", &position, &enabled, nil)
   316  
   317  			Expect(handler).To(HaveAllRequestsCalled())
   318  			Expect(apiErr).NotTo(HaveOccurred())
   319  
   320  			Expect(created.GUID).NotTo(BeNil())
   321  			Expect(created.Name).To(Equal("my-cool-buildpack"))
   322  			Expect(999).To(Equal(*created.Position))
   323  		})
   324  	})
   325  
   326  	It("deletes buildpacks", func() {
   327  		setupTestServer(apifakes.NewCloudControllerTestRequest(testnet.TestRequest{
   328  			Method: "DELETE",
   329  			Path:   "/v2/buildpacks/my-cool-buildpack-guid",
   330  			Response: testnet.TestResponse{
   331  				Status: http.StatusNoContent,
   332  			}}))
   333  
   334  		err := repo.Delete("my-cool-buildpack-guid")
   335  
   336  		Expect(handler).To(HaveAllRequestsCalled())
   337  		Expect(err).NotTo(HaveOccurred())
   338  	})
   339  
   340  	Describe("updating buildpacks", func() {
   341  		It("updates a buildpack's name, position and enabled flag", func() {
   342  			setupTestServer(apifakes.NewCloudControllerTestRequest(testnet.TestRequest{
   343  				Method:  "PUT",
   344  				Path:    "/v2/buildpacks/my-cool-buildpack-guid",
   345  				Matcher: testnet.RequestBodyMatcher(`{"name":"my-cool-buildpack","position":555,"enabled":false}`),
   346  				Response: testnet.TestResponse{
   347  					Status: http.StatusCreated,
   348  					Body: `{
   349  						"metadata": {
   350  							"guid": "my-cool-buildpack-guid"
   351  						},
   352  						"entity": {
   353  							"name": "my-cool-buildpack",
   354  							"position":555,
   355  							"enabled":false
   356  						}
   357  					}`},
   358  			}))
   359  
   360  			position := 555
   361  			enabled := false
   362  			buildpack := models.Buildpack{
   363  				Name:     "my-cool-buildpack",
   364  				GUID:     "my-cool-buildpack-guid",
   365  				Position: &position,
   366  				Enabled:  &enabled,
   367  			}
   368  
   369  			updated, err := repo.Update(buildpack)
   370  
   371  			Expect(handler).To(HaveAllRequestsCalled())
   372  			Expect(err).NotTo(HaveOccurred())
   373  			Expect(updated).To(Equal(buildpack))
   374  		})
   375  
   376  		It("sets the locked attribute on the buildpack", func() {
   377  			setupTestServer(apifakes.NewCloudControllerTestRequest(testnet.TestRequest{
   378  				Method:  "PUT",
   379  				Path:    "/v2/buildpacks/my-cool-buildpack-guid",
   380  				Matcher: testnet.RequestBodyMatcher(`{"name":"my-cool-buildpack","locked":true}`),
   381  				Response: testnet.TestResponse{
   382  					Status: http.StatusCreated,
   383  					Body: `{
   384  
   385  						"metadata": {
   386  							"guid": "my-cool-buildpack-guid"
   387  						},
   388  						"entity": {
   389  							"name": "my-cool-buildpack",
   390  							"position":123,
   391  							"locked": true
   392  						}
   393  					}`},
   394  			}))
   395  
   396  			locked := true
   397  
   398  			buildpack := models.Buildpack{
   399  				Name:   "my-cool-buildpack",
   400  				GUID:   "my-cool-buildpack-guid",
   401  				Locked: &locked,
   402  			}
   403  
   404  			updated, err := repo.Update(buildpack)
   405  
   406  			Expect(handler).To(HaveAllRequestsCalled())
   407  			Expect(err).NotTo(HaveOccurred())
   408  
   409  			position := 123
   410  			Expect(updated).To(Equal(models.Buildpack{
   411  				Name:     "my-cool-buildpack",
   412  				GUID:     "my-cool-buildpack-guid",
   413  				Position: &position,
   414  				Locked:   &locked,
   415  			}))
   416  		})
   417  	})
   418  })