github.com/fipar/percona-agent@v1.0.13/pct/update_test.go (about) 1 /* 2 Copyright (c) 2014-2015, Percona LLC and/or its affiliates. All rights reserved. 3 4 This program is free software: you can redistribute it and/or modify 5 it under the terms of the GNU Affero General Public License as published by 6 the Free Software Foundation, either version 3 of the License, or 7 (at your option) any later version. 8 9 This program is distributed in the hope that it will be useful, 10 but WITHOUT ANY WARRANTY; without even the implied warranty of 11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 GNU Affero General Public License for more details. 13 14 You should have received a copy of the GNU Affero General Public License 15 along with this program. If not, see <http://www.gnu.org/licenses/> 16 */ 17 18 package pct_test 19 20 import ( 21 "bytes" 22 "github.com/percona/cloud-protocol/proto/v1" 23 "github.com/percona/percona-agent/pct" 24 "github.com/percona/percona-agent/test" 25 "github.com/percona/percona-agent/test/mock" 26 . "gopkg.in/check.v1" 27 "io/ioutil" 28 "os" 29 "os/exec" 30 "path/filepath" 31 "strings" 32 ) 33 34 type UpdateTestSuite struct { 35 tmpDir string 36 logChan chan *proto.LogEntry 37 logger *pct.Logger 38 api *mock.API 39 pubKey []byte 40 bin []byte 41 sig []byte 42 } 43 44 var _ = Suite(&UpdateTestSuite{}) 45 46 func (s *UpdateTestSuite) SetUpSuite(t *C) { 47 var err error 48 s.tmpDir, err = ioutil.TempDir("/tmp", "percona-agent-test-pct-update") 49 t.Assert(err, IsNil) 50 51 s.logChan = make(chan *proto.LogEntry, 1000) 52 s.logger = pct.NewLogger(s.logChan, "qan-test") 53 54 links := map[string]string{ 55 "agent": "http://localhost/agent", 56 "instances": "http://localhost/instances", 57 "update": "http://localhost/update", 58 } 59 s.api = mock.NewAPI("http://localhost", "http://localhost", "123", "abc-123-def", links) 60 61 test.CopyFile(test.RootDir+"/pct/fake-percona-agent-1.0.1.go", s.tmpDir) 62 63 cwd, err := os.Getwd() 64 t.Assert(err, IsNil) 65 defer os.Chdir(cwd) 66 67 err = os.Chdir(s.tmpDir) 68 t.Assert(err, IsNil) 69 70 out, err := exec.Command("go", "build", "fake-percona-agent-1.0.1.go").Output() 71 if err != nil { 72 t.Logf("%s", out) 73 t.Fatal(err) 74 } 75 s.bin, s.sig, err = test.Sign(filepath.Join(s.tmpDir, "fake-percona-agent-1.0.1")) 76 t.Assert(err, IsNil) 77 78 s.pubKey, err = ioutil.ReadFile(filepath.Join(test.RootDir, "pct", "key.pub")) 79 t.Assert(err, IsNil) 80 } 81 82 func (s *UpdateTestSuite) TearDownSuite(t *C) { 83 if err := os.RemoveAll(s.tmpDir); err != nil { 84 t.Error(err) 85 } 86 } 87 88 // -------------------------------------------------------------------------- 89 90 func (s *UpdateTestSuite) TestCheck(t *C) { 91 // First make a very fake percona-agent "binary": just a file containing "A". 92 // Later we'll check that the update process overwrites this with the updated binary. 93 curBin := filepath.Join(s.tmpDir + "/percona-agent") 94 if err := ioutil.WriteFile(curBin, []byte{0x41}, os.FileMode(0655)); err != nil { 95 t.Fatal(err) 96 } 97 98 // Create an updater. Normally we'd pass in hard-coded pct.PublicKey and os.Args[0]. 99 u := pct.NewUpdater(s.logger, s.api, s.pubKey, curBin, "1.0.0") 100 t.Assert(u, NotNil) 101 102 // Updater.Update() makes 2 API calls: first to get percona-agent-VERSION-ARCH.gz, 103 // second to get the corresponding .sig file. The bin and sig here are "real" in 104 // the sense that in SetUpSuite() we compiled a fake percona-agent bin and signed 105 // it with the test private key (test/pct/key.pem). 106 s.api.GetCode = []int{200, 200} 107 s.api.GetData = [][]byte{s.bin, s.sig} 108 s.api.GetError = []error{nil, nil} 109 110 // Run the update process. It thinks it's getting percona-agent 1.0.1 from the real API. 111 err := u.Update("1.0.1") 112 t.Assert(err, IsNil) 113 114 // The update process should have fetched and verified the test bin and sig, then 115 // write the bin to disk and copied it over the very fake percona-agent "binary" 116 // we created first. So the whole process looks like: 117 // 1. Test writes percona-agent (very fake binary) 118 // 2. Test compiles fake-percona-agent-1.0.1.go to fake-percona-agent-1.0.1 (bin) 119 // 3. Test queues bytes of fake-percona-agent-go-1.0.1 (bin) and sig in fake API 120 // 4. Updater gets those ^ bytes, verifies bin with sig 121 // 5. Updater writes bin bytes as percona-agent-1.0.1-ARCH 122 // 6. Updater runs "percona-agent-1.0.1-ARCH -version", expects output to be "1.0.1" 123 // 7. Update does "mv percona-agent-1.0.1-ARCH percona-agent" 124 // Therefore, fake-percona-agent-1.0.1 (bin) == percona-agent at the byte level. 125 newBin, err := ioutil.ReadFile(curBin) 126 t.Assert(err, IsNil) 127 if bytes.Compare(s.bin, newBin) != 0 { 128 t.Error("percona-agent binary != fake-percona-agent-1.0.1 binary") 129 } 130 131 // And if percona-agent is *really* fake-percona-agent-1.0.1, then we too should 132 // get "1.0.1" if we run it with -version: 133 out, err := exec.Command(curBin, "-version").Output() 134 t.Assert(err, IsNil) 135 t.Check(strings.TrimSpace(string(out)), Equals, "percona-agent 1.0.1 rev 19b6b2ede12bfd2a012d40ac572a660be7aff1e7") 136 }