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