github.com/jghiloni/cli@v6.28.1-0.20170628223758-0ce05fe032a2+incompatible/api/cloudcontroller/ccv3/package_test.go (about) 1 package ccv3_test 2 3 import ( 4 "fmt" 5 "io/ioutil" 6 "net/http" 7 "os" 8 "strings" 9 10 "code.cloudfoundry.org/cli/api/cloudcontroller/ccerror" 11 . "code.cloudfoundry.org/cli/api/cloudcontroller/ccv3" 12 . "github.com/onsi/ginkgo" 13 . "github.com/onsi/gomega" 14 . "github.com/onsi/gomega/gbytes" 15 . "github.com/onsi/gomega/ghttp" 16 ) 17 18 var _ = Describe("Package", func() { 19 var client *Client 20 21 BeforeEach(func() { 22 client = NewTestClient() 23 }) 24 25 Describe("GetPackage", func() { 26 Context("when the package exist", func() { 27 BeforeEach(func() { 28 response := `{ 29 "guid": "some-pkg-guid", 30 "state": "PROCESSING_UPLOAD", 31 "links": { 32 "upload": { 33 "href": "some-package-upload-url", 34 "method": "POST" 35 } 36 } 37 }` 38 server.AppendHandlers( 39 CombineHandlers( 40 VerifyRequest(http.MethodGet, "/v3/packages/some-pkg-guid"), 41 RespondWith(http.StatusOK, response, http.Header{"X-Cf-Warnings": {"this is a warning"}}), 42 ), 43 ) 44 }) 45 46 It("returns the queried packages and all warnings", func() { 47 pkg, warnings, err := client.GetPackage("some-pkg-guid") 48 Expect(err).NotTo(HaveOccurred()) 49 50 expectedPackage := Package{ 51 GUID: "some-pkg-guid", 52 State: PackageStateProcessingUpload, 53 Links: map[string]APILink{ 54 "upload": APILink{HREF: "some-package-upload-url", Method: http.MethodPost}, 55 }, 56 } 57 Expect(pkg).To(Equal(expectedPackage)) 58 Expect(warnings).To(ConsistOf("this is a warning")) 59 }) 60 }) 61 62 Context("when the cloud controller returns errors and warnings", func() { 63 BeforeEach(func() { 64 response := `{ 65 "errors": [ 66 { 67 "code": 10008, 68 "detail": "The request is semantically invalid: command presence", 69 "title": "CF-UnprocessableEntity" 70 }, 71 { 72 "code": 10010, 73 "detail": "Package not found", 74 "title": "CF-ResourceNotFound" 75 } 76 ] 77 }` 78 server.AppendHandlers( 79 CombineHandlers( 80 VerifyRequest(http.MethodGet, "/v3/packages/some-pkg-guid"), 81 RespondWith(http.StatusTeapot, response, http.Header{"X-Cf-Warnings": {"this is a warning"}}), 82 ), 83 ) 84 }) 85 86 It("returns the error and all warnings", func() { 87 _, warnings, err := client.GetPackage("some-pkg-guid") 88 Expect(err).To(MatchError(ccerror.V3UnexpectedResponseError{ 89 ResponseCode: http.StatusTeapot, 90 V3ErrorResponse: ccerror.V3ErrorResponse{ 91 []ccerror.V3Error{ 92 { 93 Code: 10008, 94 Detail: "The request is semantically invalid: command presence", 95 Title: "CF-UnprocessableEntity", 96 }, 97 { 98 Code: 10010, 99 Detail: "Package not found", 100 Title: "CF-ResourceNotFound", 101 }, 102 }, 103 }, 104 })) 105 Expect(warnings).To(ConsistOf("this is a warning")) 106 }) 107 }) 108 }) 109 110 Describe("CreatePackage", func() { 111 Context("when the package successfully is created", func() { 112 BeforeEach(func() { 113 response := `{ 114 "guid": "some-pkg-guid", 115 "type": "bits", 116 "state": "PROCESSING_UPLOAD", 117 "links": { 118 "upload": { 119 "href": "some-package-upload-url", 120 "method": "POST" 121 } 122 } 123 }` 124 125 expectedBody := map[string]interface{}{ 126 "type": "bits", 127 "relationships": map[string]interface{}{ 128 "app": map[string]interface{}{ 129 "data": map[string]string{ 130 "guid": "some-app-guid", 131 }, 132 }, 133 }, 134 } 135 server.AppendHandlers( 136 CombineHandlers( 137 VerifyRequest(http.MethodPost, "/v3/packages"), 138 VerifyJSONRepresenting(expectedBody), 139 RespondWith(http.StatusCreated, response, http.Header{"X-Cf-Warnings": {"this is a warning"}}), 140 ), 141 ) 142 }) 143 144 It("returns the created package and warnings", func() { 145 pkg, warnings, err := client.CreatePackage(Package{ 146 Type: PackageTypeBits, 147 Relationships: Relationships{ 148 ApplicationRelationship: Relationship{GUID: "some-app-guid"}, 149 }, 150 }) 151 152 Expect(err).NotTo(HaveOccurred()) 153 Expect(warnings).To(ConsistOf("this is a warning")) 154 155 expectedPackage := Package{ 156 GUID: "some-pkg-guid", 157 Type: PackageTypeBits, 158 State: PackageStateProcessingUpload, 159 Links: map[string]APILink{ 160 "upload": APILink{HREF: "some-package-upload-url", Method: http.MethodPost}, 161 }, 162 } 163 Expect(pkg).To(Equal(expectedPackage)) 164 }) 165 }) 166 167 Context("when cc returns back an error or warnings", func() { 168 BeforeEach(func() { 169 response := ` { 170 "errors": [ 171 { 172 "code": 10008, 173 "detail": "The request is semantically invalid: command presence", 174 "title": "CF-UnprocessableEntity" 175 }, 176 { 177 "code": 10010, 178 "detail": "Package not found", 179 "title": "CF-ResourceNotFound" 180 } 181 ] 182 }` 183 server.AppendHandlers( 184 CombineHandlers( 185 VerifyRequest(http.MethodPost, "/v3/packages"), 186 RespondWith(http.StatusTeapot, response, http.Header{"X-Cf-Warnings": {"this is a warning"}}), 187 ), 188 ) 189 }) 190 191 It("returns the error and all warnings", func() { 192 _, warnings, err := client.CreatePackage(Package{}) 193 Expect(err).To(MatchError(ccerror.V3UnexpectedResponseError{ 194 ResponseCode: http.StatusTeapot, 195 V3ErrorResponse: ccerror.V3ErrorResponse{ 196 []ccerror.V3Error{ 197 { 198 Code: 10008, 199 Detail: "The request is semantically invalid: command presence", 200 Title: "CF-UnprocessableEntity", 201 }, 202 { 203 Code: 10010, 204 Detail: "Package not found", 205 Title: "CF-ResourceNotFound", 206 }, 207 }, 208 }, 209 })) 210 Expect(warnings).To(ConsistOf("this is a warning")) 211 }) 212 }) 213 }) 214 215 Describe("UploadPackage", func() { 216 Context("when the package successfully is created", func() { 217 var tempFile *os.File 218 219 BeforeEach(func() { 220 var err error 221 tempFile, err = ioutil.TempFile("", "package-upload") 222 Expect(err).ToNot(HaveOccurred()) 223 defer tempFile.Close() 224 225 fileSize := 1024 226 contents := strings.Repeat("A", fileSize) 227 err = ioutil.WriteFile(tempFile.Name(), []byte(contents), 0666) 228 Expect(err).NotTo(HaveOccurred()) 229 230 verifyHeaderAndBody := func(_ http.ResponseWriter, req *http.Request) { 231 contentType := req.Header.Get("Content-Type") 232 Expect(contentType).To(MatchRegexp("multipart/form-data; boundary=[\\w\\d]+")) 233 234 boundary := contentType[30:] 235 236 defer req.Body.Close() 237 rawBody, err := ioutil.ReadAll(req.Body) 238 Expect(err).NotTo(HaveOccurred()) 239 body := BufferWithBytes(rawBody) 240 Expect(body).To(Say("--%s", boundary)) 241 Expect(body).To(Say(`name="bits"`)) 242 Expect(body).To(Say(contents)) 243 Expect(body).To(Say("--%s--", boundary)) 244 } 245 246 response := `{ 247 "guid": "some-pkg-guid", 248 "state": "PROCESSING_UPLOAD", 249 "links": { 250 "upload": { 251 "href": "some-package-upload-url", 252 "method": "POST" 253 } 254 } 255 }` 256 257 server.AppendHandlers( 258 CombineHandlers( 259 VerifyRequest(http.MethodPost, "/v3/my-special-endpoint/some-pkg-guid/upload"), 260 verifyHeaderAndBody, 261 RespondWith(http.StatusOK, response, http.Header{"X-Cf-Warnings": {"this is a warning"}}), 262 ), 263 ) 264 }) 265 266 AfterEach(func() { 267 if tempFile != nil { 268 Expect(os.Remove(tempFile.Name())).ToNot(HaveOccurred()) 269 } 270 }) 271 272 It("returns the created package and warnings", func() { 273 pkg, warnings, err := client.UploadPackage(Package{ 274 State: PackageStateAwaitingUpload, 275 Links: map[string]APILink{ 276 "upload": APILink{ 277 HREF: fmt.Sprintf("%s/v3/my-special-endpoint/some-pkg-guid/upload", server.URL()), 278 Method: http.MethodPost, 279 }, 280 }, 281 }, tempFile.Name()) 282 283 Expect(err).NotTo(HaveOccurred()) 284 285 expectedPackage := Package{ 286 GUID: "some-pkg-guid", 287 State: PackageStateProcessingUpload, 288 Links: map[string]APILink{ 289 "upload": APILink{HREF: "some-package-upload-url", Method: http.MethodPost}, 290 }, 291 } 292 Expect(pkg).To(Equal(expectedPackage)) 293 Expect(warnings).To(ConsistOf("this is a warning")) 294 }) 295 }) 296 297 Context("when the package does not have an upload link", func() { 298 It("returns an UploadLinkNotFoundError", func() { 299 _, _, err := client.UploadPackage(Package{GUID: "some-pkg-guid", State: PackageStateAwaitingUpload}, "/path/to/foo") 300 Expect(err).To(MatchError(ccerror.UploadLinkNotFoundError{PackageGUID: "some-pkg-guid"})) 301 }) 302 }) 303 }) 304 })