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  })