github.com/niedbalski/juju@v0.0.0-20190215020005-8ff100488e47/environs/imagedownloads/simplestreams_test.go (about) 1 // Copyright 2016 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package imagedownloads_test 5 6 import ( 7 "fmt" 8 "net/http" 9 "net/http/httptest" 10 "strings" 11 12 "github.com/juju/testing" 13 jc "github.com/juju/testing/checkers" 14 gc "gopkg.in/check.v1" 15 16 . "github.com/juju/juju/environs/imagedownloads" 17 "github.com/juju/juju/environs/imagemetadata" 18 "github.com/juju/juju/environs/simplestreams" 19 ) 20 21 type Suite struct { 22 testing.IsolationSuite 23 } 24 25 var _ = gc.Suite(&Suite{}) 26 27 func newTestDataSource(s string) simplestreams.DataSource { 28 return NewDataSource(s + "/" + imagemetadata.ReleasedImagesPath) 29 } 30 31 func newTestDataSourceFunc(s string) func() simplestreams.DataSource { 32 return func() simplestreams.DataSource { 33 return NewDataSource(s + "/releases/") 34 } 35 } 36 37 func (Suite) TestNewSignedImagesSource(c *gc.C) { 38 got := DefaultSource() 39 c.Check(got.Description(), jc.DeepEquals, "ubuntu cloud images") 40 c.Check(got.PublicSigningKey(), jc.DeepEquals, imagemetadata.SimplestreamsImagesPublicKey) 41 c.Check(got.RequireSigned(), jc.IsTrue) 42 gotURL, err := got.URL("") 43 c.Assert(err, jc.ErrorIsNil) 44 c.Assert(gotURL, jc.DeepEquals, "http://cloud-images.ubuntu.com/releases/") 45 } 46 47 func (Suite) TestFetchManyDefaultFilter(c *gc.C) { 48 ts := httptest.NewServer(&sstreamsHandler{}) 49 defer ts.Close() 50 tds := []simplestreams.DataSource{ 51 newTestDataSource(ts.URL)} 52 constraints := imagemetadata.NewImageConstraint( 53 simplestreams.LookupParams{ 54 Arches: []string{"amd64", "arm64", "ppc64el"}, 55 Series: []string{"xenial"}, 56 Stream: "released", 57 }, 58 ) 59 got, resolveInfo, err := Fetch(tds, constraints, nil) 60 c.Check(resolveInfo.Signed, jc.IsTrue) 61 c.Check(err, jc.ErrorIsNil) 62 c.Assert(len(got), jc.DeepEquals, 27) 63 for _, v := range got { 64 gotURL, err := v.DownloadURL() 65 c.Check(err, jc.ErrorIsNil) 66 c.Check(strings.HasSuffix(gotURL.String(), v.FType), jc.IsTrue) 67 c.Check(strings.Contains(gotURL.String(), v.Release), jc.IsTrue) 68 c.Check(strings.Contains(gotURL.String(), v.Version), jc.IsTrue) 69 } 70 } 71 72 func (Suite) TestFetchSingleDefaultFilter(c *gc.C) { 73 ts := httptest.NewServer(&sstreamsHandler{}) 74 defer ts.Close() 75 tds := []simplestreams.DataSource{ 76 newTestDataSource(ts.URL)} 77 constraints := &imagemetadata.ImageConstraint{ 78 simplestreams.LookupParams{ 79 Arches: []string{"ppc64el"}, 80 Series: []string{"trusty"}, 81 }} 82 got, resolveInfo, err := Fetch(tds, constraints, nil) 83 c.Check(resolveInfo.Signed, jc.IsTrue) 84 c.Check(err, jc.ErrorIsNil) 85 c.Assert(len(got), jc.DeepEquals, 6) 86 c.Check(got[0].Arch, jc.DeepEquals, "ppc64el") 87 c.Check(err, jc.ErrorIsNil) 88 for _, v := range got { 89 gotURL, err := v.DownloadURL() 90 c.Check(err, jc.ErrorIsNil) 91 c.Check(strings.HasSuffix(gotURL.String(), v.FType), jc.IsTrue) 92 } 93 } 94 95 func (Suite) TestFetchOneWithFilter(c *gc.C) { 96 ts := httptest.NewServer(&sstreamsHandler{}) 97 defer ts.Close() 98 tds := []simplestreams.DataSource{ 99 newTestDataSource(ts.URL)} 100 constraints := &imagemetadata.ImageConstraint{ 101 simplestreams.LookupParams{ 102 Arches: []string{"ppc64el"}, 103 Series: []string{"xenial"}, 104 }} 105 got, resolveInfo, err := Fetch(tds, constraints, Filter("disk1.img")) 106 c.Check(resolveInfo.Signed, jc.IsTrue) 107 c.Check(err, jc.ErrorIsNil) 108 c.Assert(len(got), jc.DeepEquals, 1) 109 c.Check(got[0].Arch, jc.DeepEquals, "ppc64el") 110 gotURL, err := got[0].DownloadURL() 111 c.Assert(err, jc.ErrorIsNil) 112 c.Assert( 113 gotURL.String(), 114 jc.DeepEquals, 115 "http://cloud-images.ubuntu.com/server/releases/xenial/release-20161020/ubuntu-16.04-server-cloudimg-ppc64el-disk1.img") 116 } 117 118 func (Suite) TestFetchManyWithFilter(c *gc.C) { 119 ts := httptest.NewServer(&sstreamsHandler{}) 120 defer ts.Close() 121 tds := []simplestreams.DataSource{ 122 newTestDataSource(ts.URL)} 123 constraints := &imagemetadata.ImageConstraint{ 124 simplestreams.LookupParams{ 125 Arches: []string{"amd64", "arm64", "ppc64el"}, 126 Series: []string{"xenial"}, 127 }} 128 got, resolveInfo, err := Fetch(tds, constraints, Filter("disk1.img")) 129 c.Check(resolveInfo.Signed, jc.IsTrue) 130 c.Check(err, jc.ErrorIsNil) 131 c.Assert(len(got), jc.DeepEquals, 3) 132 c.Check(got[0].Arch, jc.DeepEquals, "amd64") 133 c.Check(got[1].Arch, jc.DeepEquals, "arm64") 134 c.Check(got[2].Arch, jc.DeepEquals, "ppc64el") 135 for i, arch := range []string{"amd64", "arm64", "ppc64el"} { 136 wantURL := fmt.Sprintf("http://cloud-images.ubuntu.com/server/releases/xenial/release-20161020/ubuntu-16.04-server-cloudimg-%s-disk1.img", arch) 137 gotURL, err := got[i].DownloadURL() 138 c.Check(err, jc.ErrorIsNil) 139 c.Check(gotURL.String(), jc.DeepEquals, wantURL) 140 141 } 142 } 143 144 func (Suite) TestOneAmd64PreciseTarGz(c *gc.C) { 145 ts := httptest.NewServer(&sstreamsHandler{}) 146 defer ts.Close() 147 got, err := One("amd64", "precise", "", "tar.gz", newTestDataSourceFunc(ts.URL)) 148 c.Check(err, jc.ErrorIsNil) 149 c.Assert(got, jc.DeepEquals, &Metadata{ 150 Arch: "amd64", 151 Release: "precise", 152 Version: "12.04", 153 FType: "tar.gz", 154 SHA256: "419d11082ee6d7e4f88dbdb8cc4f92663e834161d084ff0c1d4e812f8f19d506", 155 Path: "server/releases/precise/release-20161020.1/ubuntu-12.04-server-cloudimg-amd64.tar.gz", 156 Size: 250055789, 157 }) 158 } 159 160 func (Suite) TestOneArm64TrustyImg(c *gc.C) { 161 ts := httptest.NewServer(&sstreamsHandler{}) 162 defer ts.Close() 163 got, err := One("arm64", "trusty", "released", "disk1.img", newTestDataSourceFunc(ts.URL)) 164 c.Check(err, jc.ErrorIsNil) 165 c.Assert(got, jc.DeepEquals, &Metadata{ 166 Arch: "arm64", 167 Release: "trusty", 168 Version: "14.04", 169 FType: "disk1.img", 170 SHA256: "7da1bec20dfd78c7175155190c6fcdc16a6064be2a8bdabf13369f041c06aaf2", 171 Path: "server/releases/trusty/release-20161020/ubuntu-14.04-server-cloudimg-arm64-disk1.img", 172 Size: 356123136, 173 }) 174 } 175 176 func (Suite) TestOnePpc64elXenialImg(c *gc.C) { 177 ts := httptest.NewServer(&sstreamsHandler{}) 178 defer ts.Close() 179 got, err := One("ppc64el", "xenial", "", "disk1.img", newTestDataSourceFunc(ts.URL)) 180 c.Check(err, jc.ErrorIsNil) 181 c.Assert(got, jc.DeepEquals, &Metadata{ 182 Arch: "ppc64el", 183 Release: "xenial", 184 Version: "16.04", 185 FType: "disk1.img", 186 SHA256: "787b16d29faaa1cf2c90b7beb1a98b1e1b990fb6a5beae47c6d6f09120ed49e8", 187 Path: "server/releases/xenial/release-20161020/ubuntu-16.04-server-cloudimg-ppc64el-disk1.img", 188 Size: 320012288, 189 }) 190 } 191 192 func (Suite) TestOneErrors(c *gc.C) { 193 table := []struct { 194 description, arch, series, stream, ftype, errorMatch string 195 }{ 196 {"empty arch", "", "xenial", "", "disk1.img", `invalid parameters supplied arch=""`}, 197 {"invalid arch", "<F7>", "xenial", "", "disk1.img", `invalid parameters supplied arch="<F7>"`}, 198 {"empty series", "arm64", "", "released", "disk1.img", `invalid parameters supplied series=""`}, 199 {"invalid series", "amd64", "rusty", "", "disk1.img", `invalid parameters supplied series="rusty"`}, 200 {"empty ftype", "ppc64el", "xenial", "", "", `invalid parameters supplied ftype=""`}, 201 {"invalid file type", "amd64", "trusty", "", "tragedy", `invalid parameters supplied ftype="tragedy"`}, 202 {"all wrong except stream", "a", "t", "", "y", `invalid parameters supplied arch="a" series="t" ftype="y"`}, 203 {"stream not found", "amd64", "xenial", "hourly", "disk1.img", `no results for "amd64", "xenial", "hourly", "disk1.img"`}, 204 } 205 ts := httptest.NewServer(&sstreamsHandler{}) 206 defer ts.Close() 207 for i, test := range table { 208 c.Logf("test % 1d: %s\n", i+1, test.description) 209 _, err := One(test.arch, test.series, test.stream, test.ftype, newTestDataSourceFunc(ts.URL)) 210 c.Check(err, gc.ErrorMatches, test.errorMatch) 211 } 212 } 213 214 type sstreamsHandler struct{} 215 216 func (h sstreamsHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { 217 switch r.URL.Path { 218 case "/releases/streams/v1/index.sjson": 219 w.Header().Set("Content-Type", "application/json") 220 http.ServeFile(w, r, "testdata/index.sjson") 221 return 222 case "/releases/streams/v1/com.ubuntu.cloud:released:download.sjson": 223 w.Header().Set("Content-Type", "application/json") 224 http.ServeFile(w, r, "testdata/com.ubuntu.cloud-released-download.sjson") 225 return 226 default: 227 http.Error(w, r.URL.Path, 404) 228 return 229 } 230 }