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  }