github.com/chenbh/concourse/v6@v6.4.2/fly/integration/sync_test.go (about)

     1  package integration_test
     2  
     3  import (
     4  	"fmt"
     5  	"io/ioutil"
     6  	"net/http"
     7  	"os"
     8  	"os/exec"
     9  	"os/user"
    10  	"path/filepath"
    11  	"runtime"
    12  
    13  	"github.com/chenbh/concourse/v6/fly/version"
    14  	. "github.com/onsi/ginkgo"
    15  	. "github.com/onsi/gomega"
    16  
    17  	"github.com/onsi/gomega/gbytes"
    18  	"github.com/onsi/gomega/gexec"
    19  	"github.com/onsi/gomega/ghttp"
    20  )
    21  
    22  var _ = Describe("Syncing", func() {
    23  	var (
    24  		flyVersion string
    25  		flyPath    string
    26  	)
    27  
    28  	cliHandler := func() http.HandlerFunc {
    29  		return ghttp.CombineHandlers(
    30  			ghttp.VerifyRequest("GET", "/api/v1/cli"),
    31  			func(w http.ResponseWriter, r *http.Request) {
    32  				arch := r.URL.Query().Get("arch")
    33  				platform := r.URL.Query().Get("platform")
    34  
    35  				if arch != "amd64" && platform != runtime.GOOS {
    36  					http.Error(w, "bad params", 500)
    37  					return
    38  				}
    39  
    40  				w.WriteHeader(http.StatusOK)
    41  				fmt.Fprint(w, "this will totally execute")
    42  			},
    43  		)
    44  	}
    45  
    46  	JustBeforeEach(func() {
    47  		var err error
    48  		flyPath, err = gexec.Build(
    49  			"github.com/chenbh/concourse/v6/fly",
    50  			"-ldflags", fmt.Sprintf("-X github.com/chenbh/concourse/v6.Version=%s", flyVersion),
    51  		)
    52  		Expect(err).NotTo(HaveOccurred())
    53  
    54  		atcServer.AppendHandlers(cliHandler())
    55  	})
    56  
    57  	Context("When versions mismatch between fly + atc", func() {
    58  		BeforeEach(func() {
    59  			major, minor, patch, err := version.GetSemver(atcVersion)
    60  			Expect(err).NotTo(HaveOccurred())
    61  
    62  			flyVersion = fmt.Sprintf("%d.%d.%d", major, minor, patch+1)
    63  		})
    64  
    65  		It("downloads and replaces the currently running executable with target", func() {
    66  			downloadAndReplaceExecutable(flyPath, "-t", targetName, "sync")
    67  		})
    68  
    69  		It("downloads and replaces the currently running executable with target URL", func() {
    70  			downloadAndReplaceExecutable(flyPath, "sync", "-c", atcServer.URL())
    71  		})
    72  
    73  		Context("When the user running sync doesn't have write permissions for the target directory", func() {
    74  			It("returns an error, and doesn't download/replace the executable", func() {
    75  				me, err := user.Current()
    76  				Expect(err).ToNot(HaveOccurred())
    77  
    78  				if me.Uid == "0" {
    79  					Skip("root can always write; not worth testing")
    80  					return
    81  				}
    82  
    83  				if runtime.GOOS == "windows" {
    84  					Skip("who knows how windows works; not worth testing")
    85  					return
    86  				}
    87  
    88  				os.Chmod(filepath.Dir(flyPath), 0500)
    89  
    90  				expectedBinary := readBinary(flyPath)
    91  
    92  				flyCmd := exec.Command(flyPath, "sync", "-c", atcServer.URL())
    93  
    94  				sess, err := gexec.Start(flyCmd, GinkgoWriter, GinkgoWriter)
    95  				Expect(err).NotTo(HaveOccurred())
    96  
    97  				<-sess.Exited
    98  				Expect(sess.ExitCode()).To(Equal(1))
    99  				Expect(sess.Err).To(gbytes.Say("update failed.*permission denied"))
   100  
   101  				expectBinaryToMatch(flyPath, expectedBinary)
   102  			})
   103  		})
   104  	})
   105  
   106  	Context("When versions match between fly + atc", func() {
   107  		BeforeEach(func() {
   108  			flyVersion = atcVersion
   109  		})
   110  		It("informs the user, and doesn't download/replace the executable", func() {
   111  			expectedBinary := readBinary(flyPath)
   112  
   113  			flyCmd := exec.Command(flyPath, "sync", "-c", atcServer.URL())
   114  
   115  			sess, err := gexec.Start(flyCmd, GinkgoWriter, GinkgoWriter)
   116  			Expect(err).NotTo(HaveOccurred())
   117  
   118  			<-sess.Exited
   119  			Expect(sess.ExitCode()).To(Equal(0))
   120  			Expect(sess.Out).To(gbytes.Say(`version 4.0.0 already matches; skipping`))
   121  
   122  			expectBinaryToMatch(flyPath, expectedBinary)
   123  		})
   124  	})
   125  })
   126  
   127  func downloadAndReplaceExecutable(flyPath string, arg ...string) {
   128  	flyCmd := exec.Command(flyPath, arg...)
   129  
   130  	sess, err := gexec.Start(flyCmd, GinkgoWriter, GinkgoWriter)
   131  	Expect(err).NotTo(HaveOccurred())
   132  
   133  	<-sess.Exited
   134  	Expect(sess.ExitCode()).To(Equal(0))
   135  
   136  	expected := []byte("this will totally execute")
   137  	expectBinaryToMatch(flyPath, expected[:8])
   138  }
   139  
   140  func readBinary(path string) []byte {
   141  	expectedBinary, err := ioutil.ReadFile(flyPath)
   142  	Expect(err).NotTo(HaveOccurred())
   143  	return expectedBinary[:8]
   144  }
   145  
   146  func expectBinaryToMatch(path string, expectedBinary []byte) {
   147  	contents, err := ioutil.ReadFile(path)
   148  	Expect(err).NotTo(HaveOccurred())
   149  
   150  	// don't let ginkgo try and output the entire binary as ascii
   151  	//
   152  	// that is the way to the dark side
   153  	contents = contents[:8]
   154  	Expect(contents).To(Equal(expectedBinary))
   155  }