forked from danmux/floe
-
Notifications
You must be signed in to change notification settings - Fork 14
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
adds internal cached fetch (download) a file from remote url
- Loading branch information
Showing
23 changed files
with
1,574 additions
and
22 deletions.
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,121 @@ | ||
package nodetype | ||
|
||
import ( | ||
"crypto/md5" | ||
"crypto/sha1" | ||
"crypto/sha256" | ||
"encoding/hex" | ||
"fmt" | ||
"hash" | ||
"strings" | ||
"time" | ||
|
||
"github.com/cavaliercoder/grab" | ||
) | ||
|
||
type fetchOpts struct { | ||
URL string `json:"url"` // url of the file to download | ||
Checksum string `json:"checksum"` // the checksum (and typically filename) | ||
ChecksumAlgo string `json:"checksum-algo"` // the checksum algorithm | ||
Location string `json:"location"` // where to download | ||
} | ||
|
||
// fetch downloads stuff if it is not in the cache | ||
type fetch struct{} | ||
|
||
func (g fetch) Match(ol, or Opts) bool { | ||
return true | ||
} | ||
|
||
func (g fetch) Execute(ws *Workspace, in Opts, output chan string) (int, Opts, error) { | ||
|
||
fop := fetchOpts{} | ||
err := decode(in, &fop) | ||
if err != nil { | ||
return 255, nil, err | ||
} | ||
|
||
if fop.URL == "" { | ||
return 255, nil, fmt.Errorf("problem getting fetch url option") | ||
} | ||
if fop.Checksum == "" { | ||
output <- "(N.B. fetch without a checksum can not be trusted)" | ||
} | ||
if fop.Location == "" { | ||
fop.Location = "${ws}" | ||
} | ||
fop.Location = strings.Replace(fop.Location, "${ws}", ws.BasePath, -1) | ||
|
||
client := grab.NewClient() | ||
req, err := grab.NewRequest(ws.FetchCache, fop.URL) | ||
if err != nil { | ||
output <- fmt.Sprintf("Error setting up the download %v", err) | ||
return 255, nil, err | ||
} | ||
|
||
// set up any checksum | ||
if len(fop.Checksum) > 0 { | ||
// is it in the sum filename format ... | ||
// ba411cafee2f0f702572369da0b765e2 bodhi-4.1.0-64.iso | ||
parts := strings.Split(fop.Checksum, " ") | ||
if len(parts) > 1 { | ||
fop.Checksum = parts[0] | ||
} | ||
checksum, err := hex.DecodeString(fop.Checksum) | ||
if err != nil { | ||
output <- fmt.Sprintf("Error decoding hex checksum: %s", fop.Checksum) | ||
return 255, nil, err | ||
} | ||
|
||
var h hash.Hash | ||
switch fop.ChecksumAlgo { | ||
case "sha256": | ||
h = sha256.New() | ||
case "sha1": | ||
h = sha1.New() | ||
case "md5": | ||
h = md5.New() | ||
} | ||
req.SetChecksum(h, checksum, true) | ||
} | ||
|
||
started := time.Now() | ||
// start download | ||
output <- fmt.Sprintf("Downloading %v...", req.URL()) | ||
resp := client.Do(req) | ||
output <- fmt.Sprintf(" %v", resp.HTTPResponse.Status) | ||
|
||
// start UI loop | ||
t := time.NewTicker(300 * time.Millisecond) | ||
defer t.Stop() | ||
|
||
Loop: | ||
for { | ||
select { | ||
case <-t.C: | ||
output <- fmt.Sprintf(" %v / %v bytes (%.2f%%)", resp.BytesComplete(), resp.Size, 100*resp.Progress()) | ||
case <-resp.Done: | ||
break Loop | ||
} | ||
} | ||
|
||
// check for errors | ||
if err := resp.Err(); err != nil { | ||
output <- fmt.Sprintf("Download failed: %v", err) | ||
} else { | ||
output <- fmt.Sprintf(" %v / %v bytes (%.2f%%) in %v", resp.BytesComplete(), resp.Size, 100*resp.Progress(), time.Since(started)) | ||
output <- fmt.Sprintf("Download saved to %v", resp.Filename) | ||
} | ||
|
||
// TODO - copy to Location | ||
|
||
// Output: | ||
// Downloading http://www.golang-book.com/public/pdf/gobook.pdf... | ||
// 200 OK | ||
// transferred 42970 / 2893557 bytes (1.49%) | ||
// transferred 1207474 / 2893557 bytes (41.73%) | ||
// transferred 2758210 / 2893557 bytes (95.32%) | ||
// Download saved to ./gobook.pdf | ||
|
||
return 0, nil, nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,93 @@ | ||
package nodetype | ||
|
||
import ( | ||
"fmt" | ||
"net" | ||
"net/http" | ||
"testing" | ||
) | ||
|
||
func TestFetch(t *testing.T) { | ||
portCh := make(chan int) | ||
|
||
go serveFiles(portCh) | ||
|
||
port := <-portCh | ||
|
||
success := []string{`(100.00%)`, `Downloading`, "200 OK"} | ||
fail := []string{"404", "Not Found"} | ||
fixtures := []struct { | ||
url string | ||
algo string | ||
checksum string | ||
expected []string | ||
}{ | ||
{ // simple dl | ||
url: fmt.Sprintf("http://127.0.0.1:%d/get-file.txt", port), | ||
expected: success, | ||
}, | ||
{ // dl with sha256 check | ||
url: fmt.Sprintf("http://127.0.0.1:%d/get-file.txt", port), | ||
algo: "sha256", | ||
checksum: "864d6473d56d235de9ffb9d404e76f23e4d596ce77eae5b7ce5106f454fa7ee4 get-file.txt", | ||
expected: success, | ||
}, | ||
{ // dl with sha1 check | ||
url: fmt.Sprintf("http://127.0.0.1:%d/get-file.txt", port), | ||
algo: "sha1", | ||
checksum: "bb3357153aa8e2c0b22fef75a7f21969abb7c2b4", | ||
expected: success, | ||
}, | ||
{ // dl with sha256 check | ||
url: fmt.Sprintf("http://127.0.0.1:%d/get-file.txt", port), | ||
algo: "md5", | ||
checksum: "f35ff35df6efc82e474e97eaf10e7ff6", | ||
expected: success, | ||
}, | ||
{ // good dl bad checksum | ||
url: fmt.Sprintf("http://127.0.0.1:%d/get-file.txt", port), | ||
algo: "sha256", | ||
checksum: "load-of bollox", | ||
expected: []string{"Error", "hex", "checksum"}, | ||
}, | ||
{ // bad dl | ||
url: fmt.Sprintf("http://127.0.0.1:%d/wont_be_found", port), | ||
expected: fail, | ||
}, | ||
{ // good external check | ||
url: "https://dl.google.com/go/go1.10.2.src.tar.gz", | ||
algo: "sha256", | ||
checksum: "6264609c6b9cd8ed8e02ca84605d727ce1898d74efa79841660b2e3e985a98bd go1.10.2.src.tar.gz", | ||
expected: success, | ||
}, | ||
} | ||
|
||
for i, fx := range fixtures { | ||
opts := Opts{ | ||
"url": fx.url, | ||
"checksum": fx.checksum, | ||
"checksum-algo": fx.algo, | ||
} | ||
testNode(t, fmt.Sprintf("fetch test: %d", i), fetch{}, opts, fx.expected) | ||
} | ||
} | ||
|
||
func sayHello(w http.ResponseWriter, r *http.Request) { | ||
message := "this is a file with known hashes" | ||
w.Write([]byte(message)) | ||
} | ||
|
||
func serveFiles(portChan chan int) { | ||
|
||
listener, err := net.Listen("tcp", ":0") | ||
if err != nil { | ||
panic(err) | ||
} | ||
|
||
mux := http.NewServeMux() | ||
mux.HandleFunc("/get-file.txt", sayHello) | ||
|
||
portChan <- listener.Addr().(*net.TCPAddr).Port | ||
|
||
http.Serve(listener, mux) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.