Skip to content

Commit b8c0211

Browse files
authored
Merge pull request #168 from carolynvs/split-download-locations
Support new release scheme
2 parents a663964 + 2bfa66c commit b8c0211

34 files changed

Lines changed: 3318 additions & 1064 deletions

Gopkg.lock

Lines changed: 3 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Gopkg.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323

2424
[[constraint]]
2525
name = "github.com/Masterminds/semver"
26-
version = "1.2.2"
26+
branch = "2.x"
2727

2828
[[constraint]]
2929
name = "github.com/codegangsta/cli"

dvm-helper/dockerversion/dockerversion.go

Lines changed: 62 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -30,13 +30,69 @@ func Parse(value string) Version {
3030
v := Version{raw: value}
3131
semver, err := semver.NewVersion(value)
3232
if err == nil {
33-
v.semver = semver
33+
v.semver = &semver
3434
} else {
3535
v.alias = value
3636
}
3737
return v
3838
}
3939

40+
func (version Version) BuildDownloadURL(mirrorURL string) (url string, archived bool) {
41+
var releaseSlug, versionSlug, extSlug string
42+
43+
archivedReleaseCutoff, _ := semver.NewVersion("1.11.0-rc1")
44+
dockerStoreCutoff, _ := semver.NewVersion("17.06.0-ce")
45+
46+
var edgeVersion Version
47+
if version.IsExperimental() {
48+
// TODO: Figure out the latest edge version
49+
edgeVersion = Parse("17.06.0-ce")
50+
}
51+
52+
// Docker Store Download
53+
if version.IsExperimental() || !version.semver.LessThan(dockerStoreCutoff) {
54+
archived = true
55+
extSlug = archiveFileExt
56+
if mirrorURL == "" {
57+
mirrorURL = "download.docker.com"
58+
}
59+
if version.IsExperimental() {
60+
releaseSlug = "edge"
61+
versionSlug = edgeVersion.String()
62+
} else if version.IsPrerelease() {
63+
releaseSlug = "test"
64+
versionSlug = version.String()
65+
} else {
66+
releaseSlug = "stable"
67+
versionSlug = version.String()
68+
}
69+
70+
url = fmt.Sprintf("https://%s/%s/static/%s/%s/docker-%s%s",
71+
mirrorURL, mobyOS, releaseSlug, dockerArch, versionSlug, extSlug)
72+
return
73+
} else { // Original Download
74+
archived = !version.semver.LessThan(archivedReleaseCutoff)
75+
versionSlug = version.String()
76+
if archived {
77+
extSlug = archiveFileExt
78+
} else {
79+
extSlug = binaryFileExt
80+
}
81+
if mirrorURL == "" {
82+
mirrorURL = "docker.com"
83+
}
84+
if version.IsPrerelease() {
85+
releaseSlug = "test"
86+
} else {
87+
releaseSlug = "get"
88+
}
89+
90+
url = fmt.Sprintf("https://%s.%s/builds/%s/%s/docker-%s%s",
91+
releaseSlug, mirrorURL, dockerOS, dockerArch, versionSlug, extSlug)
92+
return
93+
}
94+
}
95+
4096
func (version Version) IsPrerelease() bool {
4197
if version.semver == nil {
4298
return false
@@ -78,11 +134,6 @@ func (version *Version) SetAsExperimental() {
78134
version.alias = ExperimentalAlias
79135
}
80136

81-
func (version Version) ShouldUseArchivedRelease() bool {
82-
cutoff, _ := semver.NewConstraint(">= 1.11.0-rc1")
83-
return version.IsExperimental() || cutoff.Check(version.semver)
84-
}
85-
86137
func (version Version) String() string {
87138
if version.alias != "" && version.semver != nil {
88139
return fmt.Sprintf("%s (%s)", version.alias, version.formatRaw())
@@ -129,7 +180,10 @@ func (version Version) InRange(r string) (bool, error) {
129180
if err != nil {
130181
return false, errors.Wrapf(err, "Unable to parse range constraint: %s", r)
131182
}
132-
return c.Check(version.semver), nil
183+
if version.semver == nil {
184+
return false, nil
185+
}
186+
return c.Matches(*version.semver) == nil, nil
133187
}
134188

135189
// Compare compares Versions v to o:
@@ -138,7 +192,7 @@ func (version Version) InRange(r string) (bool, error) {
138192
// 1 == v is greater than o
139193
func (v Version) Compare(o Version) int {
140194
if v.semver != nil && o.semver != nil {
141-
return v.semver.Compare(o.semver)
195+
return v.semver.Compare(*o.semver)
142196
}
143197

144198
return strings.Compare(v.alias, o.alias)
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
// +build !windows
2+
3+
package dockerversion
4+
5+
const archiveFileExt string = ".tgz"
6+
const binaryFileExt string = ""
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
package dockerversion
2+
3+
const dockerArch string = "i386"
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
package dockerversion
2+
3+
const dockerArch string = "x86_64"
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
package dockerversion
2+
3+
const dockerOS string = "Darwin"
4+
const mobyOS string = "mac"
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
package dockerversion
2+
3+
const dockerOS string = "Linux"
4+
const mobyOS string = "linux"
Lines changed: 76 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,76 +1,72 @@
1-
package dockerversion_test
1+
package dockerversion
22

33
import (
4+
"fmt"
5+
"net/http"
46
"testing"
57

6-
"github.com/howtowhale/dvm/dvm-helper/dockerversion"
8+
"github.com/pkg/errors"
79
"github.com/stretchr/testify/assert"
810
)
911

1012
func TestStripLeadingV(t *testing.T) {
11-
v := dockerversion.Parse("v1.0.0")
13+
v := Parse("v1.0.0")
1214
assert.Equal(t, "1.0.0", v.String(), "Leading v should be stripped from the string representation")
1315
assert.Equal(t, "1.0.0", v.Name(), "Leading v should be stripped from the name")
1416
assert.Equal(t, "1.0.0", v.Value(), "Leading v should be stripped from the version value")
1517
}
1618

1719
func TestIsPrerelease(t *testing.T) {
18-
var v dockerversion.Version
20+
var v Version
1921

20-
v = dockerversion.Parse("17.3.0-ce-rc1")
22+
v = Parse("17.3.0-ce-rc1")
2123
assert.True(t, v.IsPrerelease(), "%s should be a prerelease", v)
2224

23-
v = dockerversion.Parse("1.12.4-rc1")
25+
v = Parse("1.12.4-rc1")
2426
assert.True(t, v.IsPrerelease(), "%s should be a prerelease", v)
2527

26-
v = dockerversion.Parse("1.12.4-beta.1")
28+
v = Parse("1.12.4-beta.1")
2729
assert.True(t, v.IsPrerelease(), "%s should be a prerelease", v)
2830

29-
v = dockerversion.Parse("1.12.4-alpha-2")
31+
v = Parse("1.12.4-alpha-2")
3032
assert.True(t, v.IsPrerelease(), "%s should be a prerelease", v)
3133

32-
v = dockerversion.Parse("17.3.0-ce")
34+
v = Parse("17.3.0-ce")
3335
assert.False(t, v.IsPrerelease(), "%s should NOT be a prerelease", v)
3436
}
3537

36-
func TestPrereleaseUsesArchivedReleases(t *testing.T) {
37-
v := dockerversion.Parse("v1.12.5-rc1")
38-
39-
assert.True(t, v.ShouldUseArchivedRelease())
40-
}
41-
4238
func TestLeadingZeroInVersion(t *testing.T) {
43-
v := dockerversion.Parse("v17.03.0-ce")
39+
v := Parse("v17.03.0-ce")
4440

4541
assert.Equal(t, "17.03.0-ce", v.String(), "Leading zeroes in the version should be preserved")
4642
}
4743

4844
func TestSystemAlias(t *testing.T) {
49-
v := dockerversion.Parse(dockerversion.SystemAlias)
45+
v := Parse(SystemAlias)
5046
assert.Empty(t, v.Slug(),
5147
"The system alias should not have a slug")
52-
assert.Equal(t, dockerversion.SystemAlias, v.String(),
48+
assert.Equal(t, SystemAlias, v.String(),
5349
"An empty alias should only print the alias")
54-
assert.Equal(t, dockerversion.SystemAlias, v.Name(),
50+
assert.Equal(t, SystemAlias, v.Name(),
5551
"The name for an aliased version should be its alias")
5652
assert.Equal(t, "", v.Value(),
5753
"The value for an empty aliased version should be empty")
5854
}
5955

6056
func TestExperimentalAlias(t *testing.T) {
61-
v := dockerversion.Parse(dockerversion.ExperimentalAlias)
62-
assert.Equal(t, dockerversion.ExperimentalAlias, v.Slug(),
57+
v := Parse(ExperimentalAlias)
58+
assert.Equal(t, ExperimentalAlias, v.Slug(),
6359
"The slug for the experimental version should be 'experimental'")
64-
assert.Equal(t, dockerversion.ExperimentalAlias, v.String(),
60+
assert.Equal(t, ExperimentalAlias, v.String(),
6561
"An empty alias should only print the alias")
66-
assert.Equal(t, dockerversion.ExperimentalAlias, v.Name(),
62+
assert.Equal(t, ExperimentalAlias, v.Name(),
6763
"The name for an aliased version should be its alias")
6864
assert.Equal(t, "", v.Value(),
6965
"The value for an empty aliased version should be empty")
7066
}
7167

7268
func TestAlias(t *testing.T) {
73-
v := dockerversion.NewAlias("prod", "1.2.3")
69+
v := NewAlias("prod", "1.2.3")
7470
assert.Equal(t, "1.2.3", v.Slug(),
7571
"The slug for an aliased version should be its semver value")
7672
assert.Equal(t, "prod (1.2.3)", v.String(),
@@ -82,7 +78,7 @@ func TestAlias(t *testing.T) {
8278
}
8379

8480
func TestSemanticVersion(t *testing.T) {
85-
v := dockerversion.Parse("1.2.3")
81+
v := Parse("1.2.3")
8682
assert.Equal(t, "1.2.3", v.Slug(),
8783
"The slug for a a semantic version should be its semver value")
8884
assert.Equal(t, "1.2.3", v.String(),
@@ -94,13 +90,65 @@ func TestSemanticVersion(t *testing.T) {
9490
}
9591

9692
func TestSetAsExperimental(t *testing.T) {
97-
v := dockerversion.Parse("1.2.3")
93+
v := Parse("1.2.3")
9894
v.SetAsExperimental()
9995
assert.True(t, v.IsExperimental())
10096
}
10197

10298
func TestSetAsSystem(t *testing.T) {
103-
v := dockerversion.Parse("1.2.3")
99+
v := Parse("1.2.3")
104100
v.SetAsSystem()
105101
assert.True(t, v.IsSystem())
106-
}
102+
}
103+
104+
func TestVersion_BuildDownloadURL(t *testing.T) {
105+
testcases := map[Version]struct {
106+
wantURL string
107+
wantArchived bool
108+
}{
109+
// original download location, without compression
110+
Parse("1.10.3"): {fmt.Sprintf("https://get.docker.com/builds/%s/%s/docker-1.10.3", dockerOS, dockerArch), false},
111+
112+
// original download location, without compression, prerelease
113+
Parse("1.10.0-rc1"): {fmt.Sprintf("https://test.docker.com/builds/%s/%s/docker-1.10.0-rc1", dockerOS, dockerArch), false},
114+
115+
// compressed binaries
116+
Parse("1.11.0-rc1"): {fmt.Sprintf("https://test.docker.com/builds/%s/%s/docker-1.11.0-rc1.tgz", dockerOS, dockerArch), true},
117+
118+
// original version scheme, prerelease binaries
119+
Parse("1.13.0-rc1"): {fmt.Sprintf("https://test.docker.com/builds/%s/%s/docker-1.13.0-rc1.tgz", dockerOS, dockerArch), true},
120+
121+
// yearly notation, original download location, release location
122+
Parse("17.03.0-ce"): {fmt.Sprintf("https://get.docker.com/builds/%s/%s/docker-17.03.0-ce%s", dockerOS, dockerArch, archiveFileExt), true},
123+
124+
// docker store download
125+
Parse("17.06.0-ce"): {fmt.Sprintf("https://download.docker.com/%s/static/stable/%s/docker-17.06.0-ce.tgz", mobyOS, dockerArch), true},
126+
127+
// docker store download, prerelease
128+
Parse("17.07.0-ce-rc1"): {fmt.Sprintf("https://download.docker.com/%s/static/test/%s/docker-17.07.0-ce-rc1.tgz", mobyOS, dockerArch), true},
129+
130+
// latest edge/experimental
131+
Parse("experimental"): {fmt.Sprintf("https://download.docker.com/%s/static/edge/%s/docker-17.06.0-ce.tgz", mobyOS, dockerArch), true},
132+
}
133+
134+
for version, testcase := range testcases {
135+
t.Run(version.String(), func(t *testing.T) {
136+
gotURL, gotArchived := version.BuildDownloadURL("")
137+
if testcase.wantURL != gotURL {
138+
t.Fatalf("Expected %s to be downloaded from '%s', but got '%s'", version, testcase.wantURL, gotURL)
139+
}
140+
if testcase.wantArchived != gotArchived {
141+
t.Fatalf("Expected %s to use an archived download strategy", version)
142+
}
143+
144+
response, err := http.DefaultClient.Head(gotURL)
145+
if err != nil {
146+
t.Fatalf("%#v", errors.Wrapf(err, "Unable to download release from %s", gotURL))
147+
}
148+
149+
if response.StatusCode != 200 {
150+
t.Fatalf("Unexpected status code (%d) when downloading %s", response.StatusCode, gotURL)
151+
}
152+
})
153+
}
154+
}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
package dockerversion
2+
3+
const dockerOS string = "Windows"
4+
const mobyOS string = "win"
5+
const archiveFileExt string = ".zip"
6+
const binaryFileExt string = ".exe"

0 commit comments

Comments
 (0)