github.com/axw/juju@v0.0.0-20161005053422-4bd6544d08d4/cmd/juju/cloud/updateclouds_test.go (about)

     1  // Copyright 2016 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package cloud_test
     5  
     6  import (
     7  	"bytes"
     8  	"fmt"
     9  	"net/http"
    10  	"net/http/httptest"
    11  	"strings"
    12  
    13  	jc "github.com/juju/testing/checkers"
    14  	"golang.org/x/crypto/openpgp"
    15  	"golang.org/x/crypto/openpgp/clearsign"
    16  	gc "gopkg.in/check.v1"
    17  
    18  	jujucloud "github.com/juju/juju/cloud"
    19  	"github.com/juju/juju/cmd/juju/cloud"
    20  	sstesting "github.com/juju/juju/environs/simplestreams/testing"
    21  	"github.com/juju/juju/testing"
    22  )
    23  
    24  type updateCloudsSuite struct {
    25  	testing.FakeJujuXDGDataHomeSuite
    26  }
    27  
    28  var _ = gc.Suite(&updateCloudsSuite{})
    29  
    30  func encodeCloudYAML(c *gc.C, yaml string) string {
    31  	// TODO(wallyworld) - move test signing key elsewhere
    32  	keyring, err := openpgp.ReadArmoredKeyRing(bytes.NewBufferString(sstesting.SignedMetadataPrivateKey))
    33  	c.Assert(err, jc.ErrorIsNil)
    34  	privateKey := keyring[0].PrivateKey
    35  	err = privateKey.Decrypt([]byte(sstesting.PrivateKeyPassphrase))
    36  	c.Assert(err, jc.ErrorIsNil)
    37  
    38  	var buf bytes.Buffer
    39  	plaintext, err := clearsign.Encode(&buf, privateKey, nil)
    40  	c.Assert(err, jc.ErrorIsNil)
    41  
    42  	_, err = plaintext.Write([]byte(yaml))
    43  	c.Assert(err, jc.ErrorIsNil)
    44  	err = plaintext.Close()
    45  	c.Assert(err, jc.ErrorIsNil)
    46  	return string(buf.Bytes())
    47  }
    48  
    49  func (s *updateCloudsSuite) setupTestServer(c *gc.C, serverContent string) *httptest.Server {
    50  	return httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
    51  		switch serverContent {
    52  		case "404":
    53  			w.WriteHeader(http.StatusNotFound)
    54  		case "401":
    55  			w.WriteHeader(http.StatusUnauthorized)
    56  		case "unsigned":
    57  			fmt.Fprintln(w, serverContent)
    58  			return
    59  		}
    60  		signedContent := encodeCloudYAML(c, serverContent)
    61  		fmt.Fprintln(w, signedContent)
    62  	}))
    63  }
    64  
    65  func (s *updateCloudsSuite) TestBadArgs(c *gc.C) {
    66  	updateCmd := cloud.NewUpdateCloudsCommandForTest("")
    67  	_, err := testing.RunCommand(c, updateCmd, "extra")
    68  	c.Assert(err, gc.ErrorMatches, `unrecognized args: \["extra"\]`)
    69  }
    70  
    71  func (s *updateCloudsSuite) run(c *gc.C, url, errMsg string) string {
    72  	updateCmd := cloud.NewUpdateCloudsCommandForTest(url)
    73  	out, err := testing.RunCommand(c, updateCmd)
    74  	if errMsg == "" {
    75  		c.Assert(err, jc.ErrorIsNil)
    76  	} else {
    77  		errString := strings.Replace(err.Error(), "\n", "", -1)
    78  		c.Assert(errString, gc.Matches, errMsg)
    79  	}
    80  	return testing.Stderr(out)
    81  }
    82  
    83  func (s *updateCloudsSuite) Test404(c *gc.C) {
    84  	ts := s.setupTestServer(c, "404")
    85  	defer ts.Close()
    86  
    87  	msg := s.run(c, ts.URL, "")
    88  	c.Assert(strings.Replace(msg, "\n", "", -1), gc.Matches, "Fetching latest public cloud list...Public cloud list is unavailable right now.")
    89  }
    90  
    91  func (s *updateCloudsSuite) Test401(c *gc.C) {
    92  	ts := s.setupTestServer(c, "401")
    93  	defer ts.Close()
    94  
    95  	s.run(c, ts.URL, "unauthorised access to URL .*")
    96  }
    97  
    98  func (s *updateCloudsSuite) TestUnsignedData(c *gc.C) {
    99  	ts := s.setupTestServer(c, "unsigned")
   100  	defer ts.Close()
   101  
   102  	s.run(c, ts.URL, "error receiving updated cloud data: no PGP signature embedded in plain text data")
   103  }
   104  
   105  func (s *updateCloudsSuite) TestBadDataOnServer(c *gc.C) {
   106  	ts := s.setupTestServer(c, "bad data")
   107  	defer ts.Close()
   108  
   109  	s.run(c, ts.URL, ".*invalid cloud data received when updating clouds.*")
   110  }
   111  
   112  var sampleUpdateCloudData = `
   113  clouds:
   114    aws:
   115      type: ec2
   116      auth-types: [access-key]
   117      endpoint: http://region
   118      regions:
   119        region:
   120          endpoint: http://region/1.0
   121  `[1:]
   122  
   123  func (s *updateCloudsSuite) TestNoNewData(c *gc.C) {
   124  	clouds, err := jujucloud.ParseCloudMetadata([]byte(sampleUpdateCloudData))
   125  	c.Assert(err, jc.ErrorIsNil)
   126  	err = jujucloud.WritePublicCloudMetadata(clouds)
   127  	c.Assert(err, jc.ErrorIsNil)
   128  
   129  	ts := s.setupTestServer(c, sampleUpdateCloudData)
   130  	defer ts.Close()
   131  
   132  	msg := s.run(c, ts.URL, "")
   133  	c.Assert(strings.Replace(msg, "\n", "", -1), gc.Matches, "Fetching latest public cloud list...Your list of public clouds is up to date, see `juju clouds`.")
   134  }
   135  
   136  func (s *updateCloudsSuite) TestFirstRun(c *gc.C) {
   137  	// make sure there is nothing
   138  	err := jujucloud.WritePublicCloudMetadata(nil)
   139  	c.Assert(err, jc.ErrorIsNil)
   140  
   141  	ts := s.setupTestServer(c, sampleUpdateCloudData)
   142  	defer ts.Close()
   143  
   144  	msg := s.run(c, ts.URL, "")
   145  	publicClouds, fallbackUsed, err := jujucloud.PublicCloudMetadata(jujucloud.JujuPublicCloudsPath())
   146  	c.Assert(err, jc.ErrorIsNil)
   147  	c.Assert(fallbackUsed, jc.IsFalse)
   148  	clouds, err := jujucloud.ParseCloudMetadata([]byte(sampleUpdateCloudData))
   149  	c.Assert(err, jc.ErrorIsNil)
   150  	c.Assert(publicClouds, jc.DeepEquals, clouds)
   151  	c.Assert(msg, gc.Matches, `
   152  Fetching latest public cloud list...
   153  Updated your list of public clouds with 1 cloud added:
   154  
   155      added cloud:
   156          - aws
   157  `[1:])
   158  }
   159  
   160  func (s *updateCloudsSuite) TestNewData(c *gc.C) {
   161  	clouds, err := jujucloud.ParseCloudMetadata([]byte(sampleUpdateCloudData))
   162  	c.Assert(err, jc.ErrorIsNil)
   163  	err = jujucloud.WritePublicCloudMetadata(clouds)
   164  	c.Assert(err, jc.ErrorIsNil)
   165  
   166  	newUpdateCloudData := sampleUpdateCloudData + `
   167        anotherregion:
   168          endpoint: http://anotherregion/1.0
   169  `[1:]
   170  	ts := s.setupTestServer(c, newUpdateCloudData)
   171  	defer ts.Close()
   172  
   173  	msg := s.run(c, ts.URL, "")
   174  	publicClouds, fallbackUsed, err := jujucloud.PublicCloudMetadata(jujucloud.JujuPublicCloudsPath())
   175  	c.Assert(err, jc.ErrorIsNil)
   176  	c.Assert(fallbackUsed, jc.IsFalse)
   177  	clouds, err = jujucloud.ParseCloudMetadata([]byte(newUpdateCloudData))
   178  	c.Assert(err, jc.ErrorIsNil)
   179  	c.Assert(publicClouds, jc.DeepEquals, clouds)
   180  	c.Assert(msg, gc.Matches, `
   181  Fetching latest public cloud list...
   182  Updated your list of public clouds with 1 cloud region added:
   183  
   184      added cloud region:
   185          - aws/anotherregion
   186  `[1:])
   187  }