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 }