forked from docker/machine
-
Notifications
You must be signed in to change notification settings - Fork 0
/
b2d.go
130 lines (108 loc) · 2.67 KB
/
b2d.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
package utils
import (
"encoding/json"
"fmt"
"io"
"io/ioutil"
"net"
"net/http"
"net/url"
"os"
"path/filepath"
"time"
)
const (
timeout = time.Second * 5
)
func defaultTimeout(network, addr string) (net.Conn, error) {
return net.DialTimeout(network, addr, timeout)
}
func getClient() *http.Client {
transport := http.Transport{
DisableKeepAlives: true,
Proxy: http.ProxyFromEnvironment,
Dial: defaultTimeout,
}
client := http.Client{
Transport: &transport,
}
return &client
}
type B2dUtils struct {
githubApiBaseUrl string
githubBaseUrl string
}
func NewB2dUtils(githubApiBaseUrl, githubBaseUrl string) *B2dUtils {
defaultBaseApiUrl := "https://api.github.com"
defaultBaseUrl := "https://github.com"
if githubApiBaseUrl == "" {
githubApiBaseUrl = defaultBaseApiUrl
}
if githubBaseUrl == "" {
githubBaseUrl = defaultBaseUrl
}
return &B2dUtils{
githubApiBaseUrl: githubApiBaseUrl,
githubBaseUrl: githubBaseUrl,
}
}
// Get the latest boot2docker release tag name (e.g. "v0.6.0").
// FIXME: find or create some other way to get the "latest release" of boot2docker since the GitHub API has a pretty low rate limit on API requests
func (b *B2dUtils) GetLatestBoot2DockerReleaseURL() (string, error) {
client := getClient()
apiUrl := fmt.Sprintf("%s/repos/boot2docker/boot2docker/releases", b.githubApiBaseUrl)
rsp, err := client.Get(apiUrl)
if err != nil {
return "", err
}
defer rsp.Body.Close()
var t []struct {
TagName string `json:"tag_name"`
}
if err := json.NewDecoder(rsp.Body).Decode(&t); err != nil {
return "", err
}
if len(t) == 0 {
return "", fmt.Errorf("no releases found")
}
tag := t[0].TagName
isoUrl := fmt.Sprintf("%s/boot2docker/boot2docker/releases/download/%s/boot2docker.iso", b.githubBaseUrl, tag)
return isoUrl, nil
}
// Download boot2docker ISO image for the given tag and save it at dest.
func (b *B2dUtils) DownloadISO(dir, file, isoUrl string) error {
u, err := url.Parse(isoUrl)
var src io.ReadCloser
if u.Scheme == "file" || u.Scheme == "" {
s, err := os.Open(u.Path)
if err != nil {
return err
}
src = s
} else {
client := getClient()
s, err := client.Get(isoUrl)
if err != nil {
return err
}
src = s.Body
}
defer src.Close()
// Download to a temp file first then rename it to avoid partial download.
f, err := ioutil.TempFile(dir, file+".tmp")
if err != nil {
return err
}
defer os.Remove(f.Name())
if _, err := io.Copy(f, src); err != nil {
// TODO: display download progress?
return err
}
if err := f.Close(); err != nil {
return err
}
if err := os.Rename(f.Name(), filepath.Join(dir, file)); err != nil {
return err
}
return nil
}