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 }