github.com/cloudfoundry-attic/ltc@v0.0.0-20151123212628-098adc7919fc/cell-helpers/s3tool/main_test.go (about) 1 // +build !windows 2 3 package main_test 4 5 import ( 6 "io/ioutil" 7 "net/http" 8 "os" 9 "os/exec" 10 11 . "github.com/onsi/ginkgo" 12 . "github.com/onsi/gomega" 13 "github.com/onsi/gomega/gbytes" 14 "github.com/onsi/gomega/gexec" 15 "github.com/onsi/gomega/ghttp" 16 ) 17 18 var _ = Describe("s3tool", func() { 19 Describe("invalid action", func() { 20 It("prints an error message and exits", func() { 21 command := exec.Command(s3toolPath, "invalid") 22 session, err := gexec.Start(command, GinkgoWriter, GinkgoWriter) 23 Expect(err).NotTo(HaveOccurred()) 24 25 Eventually(session).Should(gexec.Exit(3)) 26 Expect(session.Out).To(gbytes.Say("Usage: s3tool \\[get\\|put\\|delete\\] arguments...")) 27 }) 28 }) 29 30 Describe("delete", func() { 31 var ( 32 httpStatusCode int 33 fakeServer *ghttp.Server 34 ) 35 36 BeforeEach(func() { 37 httpStatusCode = 200 38 fakeServer = ghttp.NewServer() 39 fakeServer.AppendHandlers(ghttp.CombineHandlers( 40 ghttp.VerifyRequest("DELETE", "/bucket/key"), 41 ghttp.RespondWithPtr(&httpStatusCode, nil), 42 func(_ http.ResponseWriter, req *http.Request) { 43 auth := req.Header.Get(http.CanonicalHeaderKey("Authorization")) 44 Expect(auth).To(HavePrefix("AWS")) 45 }, 46 )) 47 }) 48 49 AfterEach(func() { 50 fakeServer.Close() 51 }) 52 53 It("does a DELETE to the S3 server to delete the file", func() { 54 command := exec.Command(s3toolPath, "delete", "access", "secret", "bucket", "region", "key") 55 command.Env = []string{"AWS_ENDPOINT_OVERRIDE=" + fakeServer.URL()} 56 session, err := gexec.Start(command, GinkgoWriter, GinkgoWriter) 57 Expect(err).NotTo(HaveOccurred()) 58 59 Eventually(session).Should(gexec.Exit(0)) 60 Expect(session.Out).To(gbytes.Say("Deleted s3://bucket/key.")) 61 62 Expect(fakeServer.ReceivedRequests()).To(HaveLen(1)) 63 }) 64 65 Context("when the S3 delete fails", func() { 66 It("prints an error message and exits", func() { 67 httpStatusCode = 404 68 69 command := exec.Command(s3toolPath, "delete", "access", "secret", "bucket", "region", "key") 70 command.Env = []string{"AWS_ENDPOINT_OVERRIDE=" + fakeServer.URL()} 71 session, err := gexec.Start(command, GinkgoWriter, GinkgoWriter) 72 Expect(err).NotTo(HaveOccurred()) 73 74 Eventually(session).Should(gexec.Exit(2)) 75 Expect(session.Out).To(gbytes.Say("Error deleting s3://bucket/key: ")) 76 }) 77 }) 78 79 Context("when arguments for the delete action are invalid", func() { 80 It("prints an error message and exits", func() { 81 command := exec.Command(s3toolPath, "delete", "invalid") 82 session, err := gexec.Start(command, GinkgoWriter, GinkgoWriter) 83 Expect(err).NotTo(HaveOccurred()) 84 85 Eventually(session).Should(gexec.Exit(3)) 86 Expect(session.Out).To(gbytes.Say("Usage: s3tool delete s3AccessKey s3SecretKey s3Bucket s3Region s3Path")) 87 }) 88 }) 89 }) 90 91 Describe("get", func() { 92 var ( 93 httpStatusCode int 94 httpResponse string 95 fakeServer *ghttp.Server 96 ) 97 98 BeforeEach(func() { 99 fakeServer = ghttp.NewServer() 100 httpStatusCode = 200 101 httpResponse = "" 102 fakeServer.AppendHandlers(ghttp.CombineHandlers( 103 ghttp.VerifyRequest("GET", "/bucket/key"), 104 ghttp.RespondWithPtr(&httpStatusCode, &httpResponse), 105 func(_ http.ResponseWriter, req *http.Request) { 106 auth := req.Header.Get(http.CanonicalHeaderKey("Authorization")) 107 Expect(auth).To(HavePrefix("AWS")) 108 }, 109 )) 110 }) 111 112 AfterEach(func() { 113 fakeServer.Close() 114 }) 115 116 It("does a GET to the S3 server and saves the resulting response", func() { 117 httpResponse = "some-file-contents" 118 119 tmpFile, err := ioutil.TempFile(os.TempDir(), "downloadedFile") 120 Expect(err).NotTo(HaveOccurred()) 121 defer os.Remove(tmpFile.Name()) 122 123 command := exec.Command(s3toolPath, "get", "access", "secret", "bucket", "region", "key", tmpFile.Name()) 124 command.Env = []string{"AWS_ENDPOINT_OVERRIDE=" + fakeServer.URL()} 125 session, err := gexec.Start(command, GinkgoWriter, GinkgoWriter) 126 Expect(err).NotTo(HaveOccurred()) 127 128 Eventually(session).Should(gexec.Exit(0)) 129 Expect(session.Out).To(gbytes.Say("Downloaded s3://bucket/key to %s", tmpFile.Name())) 130 131 Expect(fakeServer.ReceivedRequests()).To(HaveLen(1)) 132 Expect(ioutil.ReadFile(tmpFile.Name())).To(Equal([]byte("some-file-contents"))) 133 }) 134 135 Context("when the S3 download fails", func() { 136 It("prints an error message and exits", func() { 137 httpStatusCode = 404 138 139 command := exec.Command(s3toolPath, "get", "access", "secret", "bucket", "region", "key", "some-missing-file") 140 command.Env = []string{"AWS_ENDPOINT_OVERRIDE=" + fakeServer.URL()} 141 session, err := gexec.Start(command, GinkgoWriter, GinkgoWriter) 142 Expect(err).NotTo(HaveOccurred()) 143 144 Eventually(session).Should(gexec.Exit(2)) 145 Expect(session.Out).To(gbytes.Say("Error downloading s3://bucket/key:")) 146 147 _, err = os.Stat("some-missing-file") 148 Expect(err).To(MatchError("stat some-missing-file: no such file or directory")) 149 }) 150 }) 151 152 Context("when the destination open fails", func() { 153 It("prints an error message and exits", func() { 154 command := exec.Command(s3toolPath, "get", "access", "secret", "bucket", "region", "key", "/") 155 command.Env = []string{"AWS_ENDPOINT_OVERRIDE=" + fakeServer.URL()} 156 session, err := gexec.Start(command, GinkgoWriter, GinkgoWriter) 157 Expect(err).NotTo(HaveOccurred()) 158 159 Eventually(session).Should(gexec.Exit(2)) 160 Expect(session.Out).To(gbytes.Say("Error opening /: ")) 161 }) 162 }) 163 164 Context("when the command is missing", func() { 165 It("prints an error message and exits", func() { 166 command := exec.Command(s3toolPath, "get", "invalid") 167 session, err := gexec.Start(command, GinkgoWriter, GinkgoWriter) 168 Expect(err).NotTo(HaveOccurred()) 169 170 Eventually(session).Should(gexec.Exit(3)) 171 Expect(session.Out).To(gbytes.Say("Usage: s3tool get s3AccessKey s3SecretKey s3Bucket s3Region s3Path destinationFilePath")) 172 }) 173 }) 174 }) 175 176 Describe("put", func() { 177 var ( 178 httpStatusCode int 179 fakeServer *ghttp.Server 180 httpBody []byte 181 tmpFile *os.File 182 ) 183 184 BeforeEach(func() { 185 httpStatusCode = 200 186 fakeServer = ghttp.NewServer() 187 fakeServer.AppendHandlers(ghttp.CombineHandlers( 188 ghttp.VerifyRequest("PUT", "/bucket/key"), 189 ghttp.RespondWithPtr(&httpStatusCode, nil), 190 func(_ http.ResponseWriter, req *http.Request) { 191 auth := req.Header.Get(http.CanonicalHeaderKey("Authorization")) 192 Expect(auth).To(HavePrefix("AWS")) 193 var err error 194 httpBody, err = ioutil.ReadAll(req.Body) 195 Expect(err).NotTo(HaveOccurred()) 196 }, 197 )) 198 199 var err error 200 tmpFile, err = ioutil.TempFile(os.TempDir(), "fileToUpload") 201 Expect(err).NotTo(HaveOccurred()) 202 203 tmpFile.Write([]byte("some-file-contents")) 204 Expect(tmpFile.Close()).To(Succeed()) 205 }) 206 207 AfterEach(func() { 208 fakeServer.Close() 209 Expect(os.Remove(tmpFile.Name())).To(Succeed()) 210 }) 211 212 It("does a PUT to the S3 server to upload the file", func() { 213 command := exec.Command(s3toolPath, "put", "access", "secret", "bucket", "region", "key", tmpFile.Name()) 214 command.Env = []string{"AWS_ENDPOINT_OVERRIDE=" + fakeServer.URL()} 215 session, err := gexec.Start(command, GinkgoWriter, GinkgoWriter) 216 Expect(err).NotTo(HaveOccurred()) 217 218 Eventually(session).Should(gexec.Exit(0)) 219 Expect(session.Out).To(gbytes.Say("Uploaded " + tmpFile.Name() + " to s3://bucket/key.")) 220 221 Expect(fakeServer.ReceivedRequests()).To(HaveLen(1)) 222 Expect(httpBody).To(Equal([]byte("some-file-contents"))) 223 }) 224 225 Context("when the S3 upload fails", func() { 226 It("prints an error message and exits", func() { 227 httpStatusCode = 404 228 229 command := exec.Command(s3toolPath, "put", "access", "secret", "bucket", "region", "key", tmpFile.Name()) 230 command.Env = []string{"AWS_ENDPOINT_OVERRIDE=" + fakeServer.URL()} 231 session, err := gexec.Start(command, GinkgoWriter, GinkgoWriter) 232 Expect(err).NotTo(HaveOccurred()) 233 234 Eventually(session).Should(gexec.Exit(2)) 235 Expect(session.Out).To(gbytes.Say("Error uploading " + tmpFile.Name() + ": 404NotFound: 404 Not Found")) 236 }) 237 }) 238 239 Context("when the source file cannot be read", func() { 240 It("prints an error message and exits", func() { 241 command := exec.Command(s3toolPath, "put", "access", "secret", "bucket", "region", "key", "some-missing-file") 242 session, err := gexec.Start(command, GinkgoWriter, GinkgoWriter) 243 Expect(err).NotTo(HaveOccurred()) 244 245 Eventually(session).Should(gexec.Exit(2)) 246 Expect(session.Out).To(gbytes.Say("Error opening some-missing-file: open some-missing-file: no such file or directory")) 247 }) 248 }) 249 250 Context("when the command is missing", func() { 251 It("prints an error message and exits", func() { 252 command := exec.Command(s3toolPath, "put", "invalid") 253 session, err := gexec.Start(command, GinkgoWriter, GinkgoWriter) 254 Expect(err).NotTo(HaveOccurred()) 255 256 Eventually(session).Should(gexec.Exit(3)) 257 Expect(session.Out).To(gbytes.Say("Usage: s3tool put s3AccessKey s3SecretKey s3Bucket s3Region s3Path fileToUpload")) 258 }) 259 }) 260 }) 261 })