dex/vendor/github.com/cockroachdb/cockroach-go/testserver/binaries.go
2016-10-03 12:48:25 -07:00

120 lines
2.7 KiB
Go

package testserver
import (
"fmt"
"io"
"io/ioutil"
"log"
"net/http"
"os"
"path/filepath"
"runtime"
"strings"
"time"
)
const (
awsBaseURL = "https://s3.amazonaws.com/cockroach/cockroach"
latestSuffix = "LATEST"
localBinaryPath = "/var/tmp"
finishedFileMode = 0555
)
func binaryName() string {
return fmt.Sprintf("cockroach.%s-%s", runtime.GOOS, runtime.GOARCH)
}
func binaryNameWithSha(sha string) string {
return fmt.Sprintf("%s.%s", binaryName(), sha)
}
func binaryPath(sha string) string {
return filepath.Join(localBinaryPath, binaryNameWithSha(sha))
}
func latestMarkerURL() string {
return fmt.Sprintf("%s/%s.%s", awsBaseURL, binaryName(), latestSuffix)
}
func binaryURL(sha string) string {
return fmt.Sprintf("%s/%s.%s", awsBaseURL, binaryName(), sha)
}
func findLatestSha() (string, error) {
markerURL := latestMarkerURL()
marker, err := http.Get(markerURL)
if err != nil {
return "", fmt.Errorf("could not download %s: %s", markerURL)
}
if marker.StatusCode == 404 {
return "", fmt.Errorf("for 404 from GET %s: make sure OS and ARCH are supported",
markerURL)
} else if marker.StatusCode != 200 {
return "", fmt.Errorf("bad response got GET %s: %d (%s)",
markerURL, marker.StatusCode, marker.Status)
}
defer marker.Body.Close()
body, err := ioutil.ReadAll(marker.Body)
if err != nil {
return "", err
}
return strings.TrimSpace(string(body)), nil
}
func downloadFile(url, filePath string) error {
output, err := os.OpenFile(filePath, os.O_WRONLY|os.O_CREATE|os.O_EXCL, 0200)
if err != nil {
return fmt.Errorf("error creating %s: %s", filePath, "-", err)
}
defer output.Close()
log.Printf("downloading %s to %s, this may take some time", url, filePath)
response, err := http.Get(url)
if err != nil {
return fmt.Errorf("error downloading %s: %s", url, err)
}
defer response.Body.Close()
if response.StatusCode != 200 {
return fmt.Errorf("error downloading %s: %d (%s)", url, response.StatusCode, response.Status)
}
_, err = io.Copy(output, response.Body)
if err != nil {
return fmt.Errorf("problem downloading %s to %s: %s", url, filePath, err)
}
// Download was successful, add the rw bits.
return os.Chmod(filePath, finishedFileMode)
}
func downloadLatestBinary() (string, error) {
sha, err := findLatestSha()
if err != nil {
return "", err
}
localFile := binaryPath(sha)
for {
finfo, err := os.Stat(localFile)
if err != nil {
// File does not exist: download it.
break
}
// File already present: check mode.
if finfo.Mode().Perm() == finishedFileMode {
return localFile, nil
}
time.Sleep(time.Millisecond * 10)
}
err = downloadFile(binaryURL(sha), localFile)
if err != nil {
_ = os.Remove(localFile)
return "", err
}
return localFile, nil
}