7167: add tests to replications count
[arvados.git] / tools / keep-rsync / keep-rsync_test.go
1 package main
2
3 import (
4         "crypto/md5"
5         "fmt"
6         "io/ioutil"
7         "os"
8         "testing"
9         "time"
10
11         "git.curoverse.com/arvados.git/sdk/go/arvadostest"
12         "git.curoverse.com/arvados.git/sdk/go/keepclient"
13
14         . "gopkg.in/check.v1"
15 )
16
17 // Gocheck boilerplate
18 func Test(t *testing.T) {
19         TestingT(t)
20 }
21
22 // Gocheck boilerplate
23 var _ = Suite(&ServerRequiredSuite{})
24
25 // Tests that require the Keep server running
26 type ServerRequiredSuite struct{}
27
28 func (s *ServerRequiredSuite) SetUpSuite(c *C) {
29 }
30
31 func (s *ServerRequiredSuite) SetUpTest(c *C) {
32         arvadostest.ResetEnv()
33         srcKeepServicesJSON = ""
34         dstKeepServicesJSON = ""
35 }
36
37 func (s *ServerRequiredSuite) TearDownSuite(c *C) {
38         arvadostest.StopKeep()
39         arvadostest.StopAPI()
40 }
41
42 // Testing keep-rsync needs two sets of keep services: src and dst.
43 // The test setup hence tweaks keep-rsync initialzation to achieve this.
44 // First invoke initializeKeepRsync and then invoke StartKeepAdditional
45 // to create the keep servers to be used as destination.
46 func setupRsync(c *C, enforcePermissions bool) {
47         // srcConfig
48         srcConfig.APIHost = os.Getenv("ARVADOS_API_HOST")
49         srcConfig.APIToken = os.Getenv("ARVADOS_API_TOKEN")
50         srcConfig.APIHostInsecure = matchTrue.MatchString(os.Getenv("ARVADOS_API_HOST_INSECURE"))
51
52         // dstConfig
53         dstConfig.APIHost = os.Getenv("ARVADOS_API_HOST")
54         dstConfig.APIToken = os.Getenv("ARVADOS_API_TOKEN")
55         dstConfig.APIHostInsecure = matchTrue.MatchString(os.Getenv("ARVADOS_API_HOST_INSECURE"))
56
57         if enforcePermissions {
58                 blobSigningKey = "zfhgfenhffzltr9dixws36j1yhksjoll2grmku38mi7yxd66h5j4q9w4jzanezacp8s6q0ro3hxakfye02152hncy6zml2ed0uc"
59         }
60
61         // Start API and Keep servers
62         arvadostest.StartAPI()
63         arvadostest.StartKeepWithParams(false, enforcePermissions)
64
65         // initialize keep-rsync
66         err := initializeKeepRsync()
67         c.Assert(err, Equals, nil)
68
69         // Create two more keep servers to be used as destination
70         arvadostest.StartKeepWithParams(true, enforcePermissions)
71
72         // load kcDst; set Want_replicas as 1 since that is how many keep servers are created for dst.
73         kcDst, err = keepclient.MakeKeepClient(&arvDst)
74         c.Assert(err, Equals, nil)
75         kcDst.Want_replicas = 1
76 }
77
78 // Test readConfigFromFile method
79 func (s *ServerRequiredSuite) TestReadConfigFromFile(c *C) {
80         // Setup a test config file
81         file, err := ioutil.TempFile(os.TempDir(), "config")
82         c.Assert(err, Equals, nil)
83         defer os.Remove(file.Name())
84
85         fileContent := "ARVADOS_API_HOST=testhost\n"
86         fileContent += "ARVADOS_API_TOKEN=testtoken\n"
87         fileContent += "ARVADOS_API_HOST_INSECURE=true\n"
88         fileContent += "ARVADOS_BLOB_SIGNING_KEY=abcdefg"
89
90         _, err = file.Write([]byte(fileContent))
91
92         // Invoke readConfigFromFile method with this test filename
93         config, err := readConfigFromFile(file.Name())
94         c.Assert(err, Equals, nil)
95         c.Assert(config.APIHost, Equals, "testhost")
96         c.Assert(config.APIToken, Equals, "testtoken")
97         c.Assert(config.APIHostInsecure, Equals, true)
98         c.Assert(config.ExternalClient, Equals, false)
99         c.Assert(blobSigningKey, Equals, "abcdefg")
100 }
101
102 // Test keep-rsync initialization, with src and dst keep servers.
103 // Do a Put and Get in src, both of which should succeed.
104 // Do a Put and Get in dst, both of which should succeed.
105 // Do a Get in dst for the src hash, which should raise block not found error.
106 // Do a Get in src for the dst hash, which should raise block not found error.
107 func (s *ServerRequiredSuite) TestRsyncPutInOne_GetFromOtherShouldFail(c *C) {
108         setupRsync(c, false)
109
110         // Put a block in src using kcSrc and Get it
111         srcData := []byte("test-data1")
112         locatorInSrc := fmt.Sprintf("%x", md5.Sum(srcData))
113
114         hash, rep, err := kcSrc.PutB(srcData)
115         c.Check(hash, Matches, fmt.Sprintf(`^%s\+10(\+.+)?$`, locatorInSrc))
116         c.Check(rep, Equals, 2)
117         c.Check(err, Equals, nil)
118
119         reader, blocklen, _, err := kcSrc.Get(locatorInSrc)
120         c.Assert(err, Equals, nil)
121         c.Check(blocklen, Equals, int64(10))
122         all, err := ioutil.ReadAll(reader)
123         c.Check(all, DeepEquals, srcData)
124
125         // Put a different block in src using kcSrc and Get it
126         dstData := []byte("test-data2")
127         locatorInDst := fmt.Sprintf("%x", md5.Sum(dstData))
128
129         hash, rep, err = kcDst.PutB(dstData)
130         c.Check(hash, Matches, fmt.Sprintf(`^%s\+10(\+.+)?$`, locatorInDst))
131         c.Check(rep, Equals, 1)
132         c.Check(err, Equals, nil)
133
134         reader, blocklen, _, err = kcDst.Get(locatorInDst)
135         c.Assert(err, Equals, nil)
136         c.Check(blocklen, Equals, int64(10))
137         all, err = ioutil.ReadAll(reader)
138         c.Check(all, DeepEquals, dstData)
139
140         // Get srcLocator using kcDst should fail with NotFound error
141         _, _, _, err = kcDst.Get(locatorInSrc)
142         c.Assert(err.Error(), Equals, "Block not found")
143
144         // Get dstLocator using kcSrc should fail with NotFound error
145         _, _, _, err = kcSrc.Get(locatorInDst)
146         c.Assert(err.Error(), Equals, "Block not found")
147 }
148
149 // Test keep-rsync initialization, with srcKeepServicesJSON
150 func (s *ServerRequiredSuite) TestRsyncInitializeWithKeepServicesJSON(c *C) {
151         srcKeepServicesJSON = "{ \"kind\":\"arvados#keepServiceList\", \"etag\":\"\", \"self_link\":\"\", \"offset\":null, \"limit\":null, \"items\":[ { \"href\":\"/keep_services/zzzzz-bi6l4-123456789012340\", \"kind\":\"arvados#keepService\", \"etag\":\"641234567890enhj7hzx432e5\", \"uuid\":\"zzzzz-bi6l4-123456789012340\", \"owner_uuid\":\"zzzzz-tpzed-123456789012345\", \"service_host\":\"keep0.zzzzz.arvadosapi.com\", \"service_port\":25107, \"service_ssl_flag\":false, \"service_type\":\"disk\", \"read_only\":false }, { \"href\":\"/keep_services/zzzzz-bi6l4-123456789012341\", \"kind\":\"arvados#keepService\", \"etag\":\"641234567890enhj7hzx432e5\", \"uuid\":\"zzzzz-bi6l4-123456789012341\", \"owner_uuid\":\"zzzzz-tpzed-123456789012345\", \"service_host\":\"keep0.zzzzz.arvadosapi.com\", \"service_port\":25108, \"service_ssl_flag\":false, \"service_type\":\"disk\", \"read_only\":false } ], \"items_available\":2 }"
152
153         setupRsync(c, false)
154
155         localRoots := kcSrc.LocalRoots()
156         c.Check(localRoots != nil, Equals, true)
157
158         foundIt := false
159         for k := range localRoots {
160                 if k == "zzzzz-bi6l4-123456789012340" {
161                         foundIt = true
162                 }
163         }
164         c.Check(foundIt, Equals, true)
165
166         foundIt = false
167         for k := range localRoots {
168                 if k == "zzzzz-bi6l4-123456789012341" {
169                         foundIt = true
170                 }
171         }
172         c.Check(foundIt, Equals, true)
173 }
174
175 // Test keep-rsync initialization, with src and dst keep servers with blobSingingKey.
176 // Do a Put and Get in src, both of which should succeed.
177 // Do a Put and Get in dst, both of which should succeed.
178 // Do a Get in dst for the src hash, which should raise block not found error.
179 // Do a Get in src for the dst hash, which should raise block not found error.
180 func (s *ServerRequiredSuite) TestRsyncWithBlobSigning_PutInOne_GetFromOtherShouldFail(c *C) {
181         setupRsync(c, true)
182
183         // Put a block in src using kcSrc and Get it
184         srcData := []byte("test-data1")
185         locatorInSrc := fmt.Sprintf("%x", md5.Sum(srcData))
186
187         hash, rep, err := kcSrc.PutB(srcData)
188         c.Check(hash, Matches, fmt.Sprintf(`^%s\+10(\+.+)?$`, locatorInSrc))
189         c.Check(rep, Equals, 2)
190         c.Check(err, Equals, nil)
191
192         tomorrow := time.Now().AddDate(0, 0, 1)
193         signedLocator := keepclient.SignLocator(locatorInSrc, arvSrc.ApiToken, tomorrow, []byte(blobSigningKey))
194
195         reader, blocklen, _, err := kcSrc.Get(signedLocator)
196         c.Assert(err, Equals, nil)
197         c.Check(blocklen, Equals, int64(10))
198         all, err := ioutil.ReadAll(reader)
199         c.Check(all, DeepEquals, srcData)
200
201         // Put a different block in src using kcSrc and Get it
202         dstData := []byte("test-data2")
203         locatorInDst := fmt.Sprintf("%x", md5.Sum(dstData))
204
205         hash, rep, err = kcDst.PutB(dstData)
206         c.Check(hash, Matches, fmt.Sprintf(`^%s\+10(\+.+)?$`, locatorInDst))
207         c.Check(rep, Equals, 1)
208         c.Check(err, Equals, nil)
209
210         signedLocator = keepclient.SignLocator(locatorInDst, arvDst.ApiToken, tomorrow, []byte(blobSigningKey))
211
212         reader, blocklen, _, err = kcDst.Get(signedLocator)
213         c.Assert(err, Equals, nil)
214         c.Check(blocklen, Equals, int64(10))
215         all, err = ioutil.ReadAll(reader)
216         c.Check(all, DeepEquals, dstData)
217
218         // Get srcLocator using kcDst should fail with NotFound error
219         signedLocator = keepclient.SignLocator(locatorInSrc, arvDst.ApiToken, tomorrow, []byte(blobSigningKey))
220         _, _, _, err = kcDst.Get(locatorInSrc)
221         c.Assert(err.Error(), Equals, "Block not found")
222
223         // Get dstLocator using kcSrc should fail with NotFound error
224         signedLocator = keepclient.SignLocator(locatorInDst, arvSrc.ApiToken, tomorrow, []byte(blobSigningKey))
225         _, _, _, err = kcSrc.Get(locatorInDst)
226         c.Assert(err.Error(), Equals, "Block not found")
227 }
228
229 // Test keep-rsync initialization with default replications count
230 func (s *ServerRequiredSuite) TestInitializeRsyncDefaultReplicationsCount(c *C) {
231         setupRsync(c, false)
232
233         // Must have got default replications value as 2 from dst discovery document
234         c.Assert(replications, Equals, 2)
235 }
236
237 // Test keep-rsync initialization with replications count argument
238 func (s *ServerRequiredSuite) TestInitializeRsyncReplicationsCount(c *C) {
239         // set replications to 3 to mimic passing input argument
240         replications = 3
241
242         setupRsync(c, false)
243
244         // Since replications value is provided, default is not used
245         c.Assert(replications, Equals, 3)
246 }