23
23
testing.LoggingSuite
26
var _ = Suite(&DirSuite{})
26
var _ = gc.Suite(&DirSuite{})
28
func (s *DirSuite) TestReadDir(c *C) {
28
func (s *DirSuite) TestReadDir(c *gc.C) {
29
29
path := testing.Charms.DirPath("dummy")
30
30
dir, err := charm.ReadDir(path)
31
c.Assert(err, gc.IsNil)
32
32
checkDummy(c, dir, path)
35
func (s *DirSuite) TestReadDirWithoutConfig(c *C) {
35
func (s *DirSuite) TestReadDirWithoutConfig(c *gc.C) {
36
36
path := testing.Charms.DirPath("varnish")
37
37
dir, err := charm.ReadDir(path)
38
c.Assert(err, gc.IsNil)
40
40
// A lacking config.yaml file still causes a proper
41
41
// Config value to be returned.
42
c.Assert(dir.Config().Options, HasLen, 0)
42
c.Assert(dir.Config().Options, gc.HasLen, 0)
45
func (s *DirSuite) TestBundleTo(c *C) {
45
func (s *DirSuite) TestBundleTo(c *gc.C) {
46
46
baseDir := c.MkDir()
47
47
charmDir := testing.Charms.ClonedDirPath(baseDir, "dummy")
48
48
var haveSymlinks = true
86
c.Assert(revf, NotNil)
86
c.Assert(revf, gc.NotNil)
87
87
reader, err := revf.Open()
88
c.Assert(err, gc.IsNil)
89
89
data, err := ioutil.ReadAll(reader)
92
c.Assert(string(data), Equals, "1")
91
c.Assert(err, gc.IsNil)
92
c.Assert(string(data), gc.Equals, "1")
94
c.Assert(metaf, NotNil)
94
c.Assert(metaf, gc.NotNil)
95
95
reader, err = metaf.Open()
96
c.Assert(err, gc.IsNil)
97
97
meta, err := charm.ReadMeta(reader)
100
c.Assert(meta.Name, Equals, "dummy")
99
c.Assert(err, gc.IsNil)
100
c.Assert(meta.Name, gc.Equals, "dummy")
102
c.Assert(instf, NotNil)
102
c.Assert(instf, gc.NotNil)
103
103
// Despite it being 0751, we pack and unpack it as 0755.
104
c.Assert(instf.Mode()&0777, Equals, os.FileMode(0755))
104
c.Assert(instf.Mode()&0777, gc.Equals, os.FileMode(0755))
106
106
if haveSymlinks {
107
c.Assert(symf, NotNil)
108
c.Assert(symf.Mode()&0777, Equals, os.FileMode(0777))
107
c.Assert(symf, gc.NotNil)
108
c.Assert(symf.Mode()&0777, gc.Equals, os.FileMode(0777))
109
109
reader, err = symf.Open()
110
c.Assert(err, gc.IsNil)
111
111
data, err = ioutil.ReadAll(reader)
114
c.Assert(string(data), Equals, "../target")
113
c.Assert(err, gc.IsNil)
114
c.Assert(string(data), gc.Equals, "../target")
116
c.Assert(symf, IsNil)
116
c.Assert(symf, gc.IsNil)
119
c.Assert(emptyf, NotNil)
120
c.Assert(emptyf.Mode()&os.ModeType, Equals, os.ModeDir)
119
c.Assert(emptyf, gc.NotNil)
120
c.Assert(emptyf.Mode()&os.ModeType, gc.Equals, os.ModeDir)
121
121
// Despite it being 0750, we pack and unpack it as 0755.
122
c.Assert(emptyf.Mode()&0777, Equals, os.FileMode(0755))
122
c.Assert(emptyf.Mode()&0777, gc.Equals, os.FileMode(0755))
125
125
// Bug #864164: Must complain if charm hooks aren't executable
126
func (s *DirSuite) TestBundleToWithNonExecutableHooks(c *C) {
126
func (s *DirSuite) TestBundleToWithNonExecutableHooks(c *gc.C) {
127
127
hooks := []string{"install", "start", "config-changed", "upgrade-charm", "stop"}
128
128
for _, relName := range []string{"foo", "bar", "self"} {
129
129
for _, kind := range []string{"joined", "changed", "departed", "broken"} {
134
134
dir := testing.Charms.Dir("all-hooks")
135
135
path := filepath.Join(c.MkDir(), "bundle.charm")
136
136
file, err := os.Create(path)
137
c.Assert(err, gc.IsNil)
138
138
err = dir.BundleTo(file)
140
c.Assert(err, gc.IsNil)
142
142
tlog := c.GetTestLog()
143
143
for _, hook := range hooks {
144
144
fullpath := filepath.Join(dir.Path, "hooks", hook)
145
145
exp := fmt.Sprintf(`^(.|\n)*WARNING juju charm: making "%s" executable in charm(.|\n)*$`, fullpath)
146
c.Assert(tlog, Matches, exp, Commentf("hook %q was not made executable", fullpath))
146
c.Assert(tlog, gc.Matches, exp, gc.Commentf("hook %q was not made executable", fullpath))
149
149
// Expand it and check the hooks' permissions
150
150
// (But do not use ExpandTo(), just use the raw zip)
151
151
f, err := os.Open(path)
152
c.Assert(err, gc.IsNil)
154
154
fi, err := f.Stat()
155
c.Assert(err, gc.IsNil)
156
156
size := fi.Size()
157
157
zipr, err := zip.NewReader(f, size)
158
c.Assert(err, gc.IsNil)
159
159
allhooks := dir.Meta().Hooks()
160
160
for _, zfile := range zipr.File {
161
161
cleanName := filepath.Clean(zfile.Name)
163
163
hookName := filepath.Base(cleanName)
164
164
if _, ok := allhooks[hookName]; ok {
165
165
perms := zfile.Mode()
166
c.Assert(perms&0100 != 0, Equals, true, Commentf("hook %q is not executable", hookName))
166
c.Assert(perms&0100 != 0, gc.Equals, true, gc.Commentf("hook %q is not executable", hookName))
172
func (s *DirSuite) TestBundleToWithBadType(c *C) {
172
func (s *DirSuite) TestBundleToWithBadType(c *gc.C) {
173
173
charmDir := testing.Charms.ClonedDirPath(c.MkDir(), "dummy")
174
174
badFile := filepath.Join(charmDir, "hooks", "badfile")
176
176
// Symlink targeting a path outside of the charm.
177
177
err := os.Symlink("../../target", badFile)
178
c.Assert(err, gc.IsNil)
180
180
dir, err := charm.ReadDir(charmDir)
181
c.Assert(err, gc.IsNil)
183
183
err = dir.BundleTo(&bytes.Buffer{})
184
c.Assert(err, ErrorMatches, `symlink "hooks/badfile" links out of charm: "../../target"`)
184
c.Assert(err, gc.ErrorMatches, `symlink "hooks/badfile" links out of charm: "../../target"`)
186
186
// Symlink targeting an absolute path.
187
187
os.Remove(badFile)
188
188
err = os.Symlink("/target", badFile)
189
c.Assert(err, gc.IsNil)
191
191
dir, err = charm.ReadDir(charmDir)
192
c.Assert(err, gc.IsNil)
194
194
err = dir.BundleTo(&bytes.Buffer{})
195
c.Assert(err, ErrorMatches, `symlink "hooks/badfile" is absolute: "/target"`)
195
c.Assert(err, gc.ErrorMatches, `symlink "hooks/badfile" is absolute: "/target"`)
197
197
// Can't bundle special files either.
198
198
os.Remove(badFile)
199
199
err = syscall.Mkfifo(badFile, 0644)
200
c.Assert(err, gc.IsNil)
202
202
dir, err = charm.ReadDir(charmDir)
203
c.Assert(err, gc.IsNil)
205
205
err = dir.BundleTo(&bytes.Buffer{})
206
c.Assert(err, ErrorMatches, `file is a named pipe: "hooks/badfile"`)
206
c.Assert(err, gc.ErrorMatches, `file is a named pipe: "hooks/badfile"`)
209
func (s *DirSuite) TestDirRevisionFile(c *C) {
209
func (s *DirSuite) TestDirRevisionFile(c *gc.C) {
210
210
charmDir := testing.Charms.ClonedDirPath(c.MkDir(), "dummy")
211
211
revPath := filepath.Join(charmDir, "revision")
213
213
// Missing revision file
214
214
err := os.Remove(revPath)
215
c.Assert(err, gc.IsNil)
217
217
dir, err := charm.ReadDir(charmDir)
219
c.Assert(dir.Revision(), Equals, 0)
218
c.Assert(err, gc.IsNil)
219
c.Assert(dir.Revision(), gc.Equals, 0)
221
221
// Missing revision file with old revision in metadata
222
222
file, err := os.OpenFile(filepath.Join(charmDir, "metadata.yaml"), os.O_WRONLY|os.O_APPEND, 0)
223
c.Assert(err, gc.IsNil)
224
224
_, err = file.Write([]byte("\nrevision: 1234\n"))
225
c.Assert(err, gc.IsNil)
227
227
dir, err = charm.ReadDir(charmDir)
229
c.Assert(dir.Revision(), Equals, 1234)
228
c.Assert(err, gc.IsNil)
229
c.Assert(dir.Revision(), gc.Equals, 1234)
231
231
// Revision file with bad content
232
232
err = ioutil.WriteFile(revPath, []byte("garbage"), 0666)
233
c.Assert(err, gc.IsNil)
235
235
dir, err = charm.ReadDir(charmDir)
236
c.Assert(err, ErrorMatches, "invalid revision file")
236
c.Assert(err, gc.ErrorMatches, "invalid revision file")
237
c.Assert(dir, gc.IsNil)
240
func (s *DirSuite) TestDirSetRevision(c *C) {
240
func (s *DirSuite) TestDirSetRevision(c *gc.C) {
241
241
dir := testing.Charms.ClonedDir(c.MkDir(), "dummy")
242
c.Assert(dir.Revision(), Equals, 1)
242
c.Assert(dir.Revision(), gc.Equals, 1)
243
243
dir.SetRevision(42)
244
c.Assert(dir.Revision(), Equals, 42)
244
c.Assert(dir.Revision(), gc.Equals, 42)
246
246
var b bytes.Buffer
247
247
err := dir.BundleTo(&b)
248
c.Assert(err, gc.IsNil)
250
250
bundle, err := charm.ReadBundleBytes(b.Bytes())
251
c.Assert(bundle.Revision(), Equals, 42)
251
c.Assert(bundle.Revision(), gc.Equals, 42)
254
func (s *DirSuite) TestDirSetDiskRevision(c *C) {
254
func (s *DirSuite) TestDirSetDiskRevision(c *gc.C) {
255
255
charmDir := testing.Charms.ClonedDirPath(c.MkDir(), "dummy")
256
256
dir, err := charm.ReadDir(charmDir)
257
c.Assert(err, gc.IsNil)
259
c.Assert(dir.Revision(), Equals, 1)
259
c.Assert(dir.Revision(), gc.Equals, 1)
260
260
dir.SetDiskRevision(42)
261
c.Assert(dir.Revision(), Equals, 42)
261
c.Assert(dir.Revision(), gc.Equals, 42)
263
263
dir, err = charm.ReadDir(charmDir)
265
c.Assert(dir.Revision(), Equals, 42)
264
c.Assert(err, gc.IsNil)
265
c.Assert(dir.Revision(), gc.Equals, 42)