1
// Copyright 2016 Canonical Ltd.
2
// Licensed under the AGPLv3, see LICENCE file for details.
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"
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"
25
type updateCloudsSuite struct {
29
var _ = gc.Suite(&updateCloudsSuite{})
31
func (s *updateCloudsSuite) SetUpTest(c *gc.C) {
32
origHome := osenv.SetJujuXDGDataHome(c.MkDir())
33
s.AddCleanup(func(*gc.C) { osenv.SetJujuXDGDataHome(origHome) })
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)
45
plaintext, err := clearsign.Encode(&buf, privateKey, nil)
46
c.Assert(err, jc.ErrorIsNil)
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())
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 {
59
w.WriteHeader(http.StatusNotFound)
61
w.WriteHeader(http.StatusUnauthorized)
63
fmt.Fprintln(w, serverContent)
66
signedContent := encodeCloudYAML(c, serverContent)
67
fmt.Fprintln(w, signedContent)
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"\]`)
77
func (s *updateCloudsSuite) run(c *gc.C, url, errMsg string) string {
78
updateCmd := cloud.NewUpdateCloudsCommandForTest(url)
79
out, err := testing.RunCommand(c, updateCmd)
81
c.Assert(err, jc.ErrorIsNil)
83
errString := strings.Replace(err.Error(), "\n", "", -1)
84
c.Assert(errString, gc.Matches, errMsg)
86
return testing.Stdout(out)
89
func (s *updateCloudsSuite) Test404(c *gc.C) {
90
ts := s.setupTestServer(c, "404")
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.")
97
func (s *updateCloudsSuite) Test401(c *gc.C) {
98
ts := s.setupTestServer(c, "401")
101
s.run(c, ts.URL, "unauthorised access to URL .*")
104
func (s *updateCloudsSuite) TestUnsignedData(c *gc.C) {
105
ts := s.setupTestServer(c, "unsigned")
108
s.run(c, ts.URL, "error receiving updated cloud data: no PGP signature embedded in plain text data")
111
func (s *updateCloudsSuite) TestBadDataOnServer(c *gc.C) {
112
ts := s.setupTestServer(c, "bad data")
115
s.run(c, ts.URL, ".*invalid cloud data received when updating clouds.*")
118
var sampleUpdateCloudData = `
122
auth-types: [access-key]
123
endpoint: http://region
126
endpoint: http://region/1.0
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)
135
ts := s.setupTestServer(c, sampleUpdateCloudData)
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 clouds`.")
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)
147
ts := s.setupTestServer(c, sampleUpdateCloudData)
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:
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)
172
newUpdateCloudData := sampleUpdateCloudData + `
174
endpoint: http://anotherregion/1.0
176
ts := s.setupTestServer(c, newUpdateCloudData)
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: