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