github.com/aaa256/atlantis@v0.0.0-20210707112435-42ee889287a2/cmd/swarm/swarm-smoke/upload_and_sync.go (about) 1 // Copyright 2018 The go-athereum Authors 2 // This file is part of go-athereum. 3 // 4 // go-athereum is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU 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 // go-athereum 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 General Public License for more details. 13 // 14 // You should have received a copy of the GNU General Public License 15 // along with go-athereum. If not, see <http://www.gnu.org/licenses/>. 16 17 package main 18 19 import ( 20 "bytes" 21 "crypto/md5" 22 "crypto/rand" 23 "fmt" 24 "io" 25 "io/ioutil" 26 "net/http" 27 "os" 28 "os/exec" 29 "strings" 30 "sync" 31 "time" 32 33 "github.com/athereum/go-athereum/log" 34 "github.com/pborman/uuid" 35 36 cli "gopkg.in/urfave/cli.v1" 37 ) 38 39 func generateEndpoints(scheme string, cluster string, from int, to int) { 40 for port := from; port <= to; port++ { 41 endpoints = append(endpoints, fmt.Sprintf("%s://%v.%s.swarm-gateways.net", scheme, port, cluster)) 42 } 43 44 if includeLocalhost { 45 endpoints = append(endpoints, "http://localhost:8500") 46 } 47 } 48 49 func cliUploadAndSync(c *cli.Context) error { 50 defer func(now time.Time) { log.Info("total time", "time", time.Since(now), "size", filesize) }(time.Now()) 51 52 generateEndpoints(scheme, cluster, from, to) 53 54 log.Info("uploading to " + endpoints[0] + " and syncing") 55 56 f, cleanup := generateRandomFile(filesize * 1000000) 57 defer cleanup() 58 59 hash, err := upload(f, endpoints[0]) 60 if err != nil { 61 log.Error(err.Error()) 62 return err 63 } 64 65 fhash, err := digest(f) 66 if err != nil { 67 log.Error(err.Error()) 68 return err 69 } 70 71 log.Info("uploaded successfully", "hash", hash, "digest", fmt.Sprintf("%x", fhash)) 72 73 if filesize < 10 { 74 time.Sleep(15 * time.Second) 75 } else { 76 time.Sleep(2 * time.Duration(filesize) * time.Second) 77 } 78 79 wg := sync.WaitGroup{} 80 for _, endpoint := range endpoints { 81 endpoint := endpoint 82 ruid := uuid.New()[:8] 83 wg.Add(1) 84 go func(endpoint string, ruid string) { 85 for { 86 err := fetch(hash, endpoint, fhash, ruid) 87 if err != nil { 88 continue 89 } 90 91 wg.Done() 92 return 93 } 94 }(endpoint, ruid) 95 } 96 wg.Wait() 97 log.Info("all endpoints synced random file successfully") 98 99 return nil 100 } 101 102 // fetch is getting the requested `hash` from the `endpoint` and compares it with the `original` file 103 func fetch(hash string, endpoint string, original []byte, ruid string) error { 104 log.Trace("sleeping", "ruid", ruid) 105 time.Sleep(1 * time.Second) 106 107 log.Trace("http get request", "ruid", ruid, "api", endpoint, "hash", hash) 108 res, err := http.Get(endpoint + "/bzz:/" + hash + "/") 109 if err != nil { 110 log.Warn(err.Error(), "ruid", ruid) 111 return err 112 } 113 log.Trace("http get response", "ruid", ruid, "api", endpoint, "hash", hash, "code", res.StatusCode, "len", res.ContentLength) 114 115 if res.StatusCode != 200 { 116 err := fmt.Errorf("expected status code %d, got %v", 200, res.StatusCode) 117 log.Warn(err.Error(), "ruid", ruid) 118 return err 119 } 120 121 defer res.Body.Close() 122 123 rdigest, err := digest(res.Body) 124 if err != nil { 125 log.Warn(err.Error(), "ruid", ruid) 126 return err 127 } 128 129 if !bytes.Equal(rdigest, original) { 130 err := fmt.Errorf("downloaded imported file md5=%x is not the same as the generated one=%x", rdigest, original) 131 log.Warn(err.Error(), "ruid", ruid) 132 return err 133 } 134 135 log.Trace("downloaded file matches random file", "ruid", ruid, "len", res.ContentLength) 136 137 return nil 138 } 139 140 // upload is uploading a file `f` to `endpoint` via the `swarm up` cmd 141 func upload(f *os.File, endpoint string) (string, error) { 142 var out bytes.Buffer 143 cmd := exec.Command("swarm", "--bzzapi", endpoint, "up", f.Name()) 144 cmd.Stdout = &out 145 err := cmd.Run() 146 if err != nil { 147 return "", err 148 } 149 hash := strings.TrimRight(out.String(), "\r\n") 150 return hash, nil 151 } 152 153 func digest(r io.Reader) ([]byte, error) { 154 h := md5.New() 155 _, err := io.Copy(h, r) 156 if err != nil { 157 return nil, err 158 } 159 return h.Sum(nil), nil 160 } 161 162 // generateRandomFile is creating a temporary file with the requested byte size 163 func generateRandomFile(size int) (f *os.File, teardown func()) { 164 // create a tmp file 165 tmp, err := ioutil.TempFile("", "swarm-test") 166 if err != nil { 167 panic(err) 168 } 169 170 // callback for tmp file cleanup 171 teardown = func() { 172 tmp.Close() 173 os.Remove(tmp.Name()) 174 } 175 176 buf := make([]byte, size) 177 _, err = rand.Read(buf) 178 if err != nil { 179 panic(err) 180 } 181 ioutil.WriteFile(tmp.Name(), buf, 0755) 182 183 return tmp, teardown 184 }