~juju-qa/ubuntu/xenial/juju/xenial-2.0-beta3

« back to all changes in this revision

Viewing changes to src/github.com/juju/juju/environs/configstore/disk_test.go

  • Committer: Martin Packman
  • Date: 2016-03-30 19:31:08 UTC
  • mfrom: (1.1.41)
  • Revision ID: martin.packman@canonical.com-20160330193108-h9iz3ak334uk0z5r
Merge new upstream source 2.0~beta3

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
// Copyright 2013 Canonical Ltd.
2
 
// Licensed under the AGPLv3, see LICENCE file for details.
3
 
 
4
 
package configstore_test
5
 
 
6
 
import (
7
 
        "fmt"
8
 
        "io/ioutil"
9
 
        "os"
10
 
        "path/filepath"
11
 
        "runtime"
12
 
        "strings"
13
 
 
14
 
        "github.com/juju/errors"
15
 
        "github.com/juju/loggo"
16
 
        jc "github.com/juju/testing/checkers"
17
 
        gc "gopkg.in/check.v1"
18
 
 
19
 
        "github.com/juju/juju/environs/configstore"
20
 
        "github.com/juju/juju/testing"
21
 
)
22
 
 
23
 
var _ = gc.Suite(&diskInterfaceSuite{})
24
 
 
25
 
type diskInterfaceSuite struct {
26
 
        interfaceSuite
27
 
        dir string
28
 
}
29
 
 
30
 
func (s *diskInterfaceSuite) SetUpTest(c *gc.C) {
31
 
        s.interfaceSuite.SetUpTest(c)
32
 
        s.dir = c.MkDir()
33
 
        s.NewStore = func(c *gc.C) configstore.Storage {
34
 
                store, err := configstore.NewDisk(s.dir)
35
 
                c.Assert(err, jc.ErrorIsNil)
36
 
                return store
37
 
        }
38
 
}
39
 
 
40
 
// storePath returns the path to the environment info
41
 
// for the named environment in the given directory.
42
 
// If envName is empty, it returns the path
43
 
// to the info files' containing directory.
44
 
func storePath(dir string, envName string) string {
45
 
        path := filepath.Join(dir, "models")
46
 
        if envName != "" {
47
 
                path = filepath.Join(path, envName+".jenv")
48
 
        }
49
 
        return path
50
 
}
51
 
 
52
 
func (s *diskInterfaceSuite) TearDownTest(c *gc.C) {
53
 
        s.NewStore = nil
54
 
        // Check that no stray temp files have been left behind
55
 
        entries, err := ioutil.ReadDir(storePath(s.dir, ""))
56
 
        c.Assert(err, jc.ErrorIsNil)
57
 
        for _, entry := range entries {
58
 
                if !strings.HasSuffix(entry.Name(), ".jenv") && entry.Name() != "cache.yaml" {
59
 
                        c.Errorf("found possible stray temp file %s, %q", s.dir, entry.Name())
60
 
                }
61
 
        }
62
 
        s.interfaceSuite.TearDownTest(c)
63
 
}
64
 
 
65
 
var _ = gc.Suite(&diskStoreSuite{})
66
 
 
67
 
type diskStoreSuite struct {
68
 
        testing.BaseSuite
69
 
}
70
 
 
71
 
func (*diskStoreSuite) TestNewDisk(c *gc.C) {
72
 
        dir := c.MkDir()
73
 
        store, err := configstore.NewDisk(filepath.Join(dir, "foo"))
74
 
        c.Assert(err, jc.Satisfies, os.IsNotExist)
75
 
        c.Assert(store, gc.IsNil)
76
 
 
77
 
        store, err = configstore.NewDisk(filepath.Join(dir))
78
 
        c.Assert(err, jc.ErrorIsNil)
79
 
        c.Assert(store, gc.NotNil)
80
 
}
81
 
 
82
 
var sampleInfo = `
83
 
  user: rog
84
 
  password: guessit
85
 
  controllers:
86
 
  - 10.0.0.1
87
 
  - 127.0.0.1
88
 
  server-hostnames:
89
 
  - example.com
90
 
  - kremvax.ru
91
 
  ca-cert: 'first line
92
 
 
93
 
    second line'
94
 
  bootstrap-config:
95
 
    secret: blah
96
 
    arble: bletch
97
 
`[1:]
98
 
 
99
 
func (*diskStoreSuite) TestRead(c *gc.C) {
100
 
        dir := c.MkDir()
101
 
        err := os.Mkdir(storePath(dir, ""), 0700)
102
 
        c.Assert(err, jc.ErrorIsNil)
103
 
        err = ioutil.WriteFile(storePath(dir, "somemodel"), []byte(sampleInfo), 0666)
104
 
        c.Assert(err, jc.ErrorIsNil)
105
 
        store, err := configstore.NewDisk(dir)
106
 
        c.Assert(err, jc.ErrorIsNil)
107
 
        info, err := store.ReadInfo("somemodel")
108
 
        c.Assert(err, jc.ErrorIsNil)
109
 
        c.Assert(info.Initialized(), jc.IsTrue)
110
 
        c.Assert(info.APICredentials(), gc.DeepEquals, configstore.APICredentials{
111
 
                User:     "rog",
112
 
                Password: "guessit",
113
 
        })
114
 
        c.Assert(info.APIEndpoint(), gc.DeepEquals, configstore.APIEndpoint{
115
 
                Addresses: []string{"10.0.0.1", "127.0.0.1"},
116
 
                Hostnames: []string{"example.com", "kremvax.ru"},
117
 
                CACert:    "first line\nsecond line",
118
 
        })
119
 
        c.Assert(info.Location(), gc.Equals, fmt.Sprintf("file %q", filepath.Join(dir, "models", "somemodel.jenv")))
120
 
        c.Assert(info.BootstrapConfig(), gc.DeepEquals, map[string]interface{}{
121
 
                "secret": "blah",
122
 
                "arble":  "bletch",
123
 
        })
124
 
}
125
 
 
126
 
func (*diskStoreSuite) TestReadNotFound(c *gc.C) {
127
 
        dir := c.MkDir()
128
 
        store, err := configstore.NewDisk(dir)
129
 
        c.Assert(err, jc.ErrorIsNil)
130
 
        info, err := store.ReadInfo("somemodel")
131
 
        c.Assert(err, jc.Satisfies, errors.IsNotFound)
132
 
        c.Assert(info, gc.IsNil)
133
 
}
134
 
 
135
 
func (*diskStoreSuite) TestWriteFails(c *gc.C) {
136
 
        dir := c.MkDir()
137
 
        store, err := configstore.NewDisk(dir)
138
 
        c.Assert(err, jc.ErrorIsNil)
139
 
 
140
 
        info := store.CreateInfo("somemodel")
141
 
 
142
 
        // Make the directory non-writable
143
 
        err = os.Chmod(storePath(dir, ""), 0555)
144
 
        c.Assert(err, jc.ErrorIsNil)
145
 
 
146
 
        // Cannot use permissions properly on windows for now
147
 
        if runtime.GOOS != "windows" {
148
 
                err = info.Write()
149
 
                c.Assert(err, gc.ErrorMatches, ".* permission denied")
150
 
        }
151
 
 
152
 
        // Make the directory writable again so that gocheck can clean it up.
153
 
        err = os.Chmod(storePath(dir, ""), 0777)
154
 
        c.Assert(err, jc.ErrorIsNil)
155
 
}
156
 
 
157
 
func (*diskStoreSuite) TestRenameFails(c *gc.C) {
158
 
        if runtime.GOOS == "windows" {
159
 
                c.Skip("issue 1403084: the way the error is checked doesn't work on windows")
160
 
        }
161
 
        dir := c.MkDir()
162
 
        store, err := configstore.NewDisk(dir)
163
 
        c.Assert(err, jc.ErrorIsNil)
164
 
 
165
 
        // Replace the file by an directory which can't be renamed over.
166
 
        path := storePath(dir, "somemodel")
167
 
        err = os.Mkdir(path, 0777)
168
 
        c.Assert(err, jc.ErrorIsNil)
169
 
 
170
 
        info := store.CreateInfo("somemodel")
171
 
        err = info.Write()
172
 
        c.Assert(err, gc.ErrorMatches, "model info already exists")
173
 
}
174
 
 
175
 
func (*diskStoreSuite) TestDestroyRemovesFiles(c *gc.C) {
176
 
        dir := c.MkDir()
177
 
        store, err := configstore.NewDisk(dir)
178
 
        c.Assert(err, jc.ErrorIsNil)
179
 
 
180
 
        info := store.CreateInfo("somemodel")
181
 
        err = info.Write()
182
 
        c.Assert(err, jc.ErrorIsNil)
183
 
 
184
 
        _, err = os.Stat(storePath(dir, "somemodel"))
185
 
        c.Assert(err, jc.ErrorIsNil)
186
 
 
187
 
        err = info.Destroy()
188
 
        c.Assert(err, jc.ErrorIsNil)
189
 
 
190
 
        _, err = os.Stat(storePath(dir, "somemodel"))
191
 
        c.Assert(err, jc.Satisfies, os.IsNotExist)
192
 
 
193
 
        err = info.Destroy()
194
 
        c.Assert(err, gc.ErrorMatches, "model info has already been removed")
195
 
}
196
 
 
197
 
func (*diskStoreSuite) TestWriteSmallerFile(c *gc.C) {
198
 
        dir := c.MkDir()
199
 
        store, err := configstore.NewDisk(dir)
200
 
        c.Assert(err, jc.ErrorIsNil)
201
 
        info := store.CreateInfo("somemodel")
202
 
        endpoint := configstore.APIEndpoint{
203
 
                Addresses: []string{"this", "is", "never", "validated", "here"},
204
 
                Hostnames: []string{"neither", "is", "this"},
205
 
                ModelUUID: testing.ModelTag.Id(),
206
 
        }
207
 
        info.SetAPIEndpoint(endpoint)
208
 
        err = info.Write()
209
 
        c.Assert(err, jc.ErrorIsNil)
210
 
 
211
 
        newInfo, err := store.ReadInfo("somemodel")
212
 
        c.Assert(err, jc.ErrorIsNil)
213
 
        // Now change the number of addresses to be shorter.
214
 
        endpoint.Addresses = []string{"just one"}
215
 
        endpoint.Hostnames = []string{"just this"}
216
 
        newInfo.SetAPIEndpoint(endpoint)
217
 
        err = newInfo.Write()
218
 
        c.Assert(err, jc.ErrorIsNil)
219
 
 
220
 
        // We should be able to read in in fine.
221
 
        yaInfo, err := store.ReadInfo("somemodel")
222
 
        c.Assert(err, jc.ErrorIsNil)
223
 
        c.Assert(yaInfo.APIEndpoint().Addresses, gc.DeepEquals, []string{"just one"})
224
 
        c.Assert(yaInfo.APIEndpoint().Hostnames, gc.DeepEquals, []string{"just this"})
225
 
}
226
 
 
227
 
func (*diskStoreSuite) TestConcurrentAccessBreaksIfTimeExceeded(c *gc.C) {
228
 
        var tw loggo.TestWriter
229
 
        c.Assert(loggo.RegisterWriter("test-log", &tw, loggo.DEBUG), gc.IsNil)
230
 
 
231
 
        dir := c.MkDir()
232
 
        store, err := configstore.NewDisk(dir)
233
 
        c.Assert(err, jc.ErrorIsNil)
234
 
 
235
 
        envDir := storePath(dir, "")
236
 
        _, err = configstore.AcquireEnvironmentLock(envDir, "blocking-op")
237
 
        c.Assert(err, jc.ErrorIsNil)
238
 
 
239
 
        _, err = store.ReadInfo("somemodel")
240
 
        c.Check(err, jc.Satisfies, errors.IsNotFound)
241
 
 
242
 
        // Using . between environments and env.lock so we don't have to care
243
 
        // about forward vs. backwards slash separator.
244
 
        messages := []jc.SimpleMessage{
245
 
                {loggo.WARNING, `breaking configstore lock, lock dir: .*models.env\.lock`},
246
 
                {loggo.WARNING, `lock holder message: pid: \d+, operation: blocking-op`},
247
 
        }
248
 
 
249
 
        c.Check(tw.Log(), jc.LogMatches, messages)
250
 
}