github.com/altoros/juju-vmware@v0.0.0-20150312064031-f19ae857ccca/service/upstart/upstart_test.go (about) 1 // Copyright 2012, 2013 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package upstart_test 5 6 import ( 7 "fmt" 8 "io/ioutil" 9 "os" 10 "path/filepath" 11 "testing" 12 13 jc "github.com/juju/testing/checkers" 14 "github.com/juju/utils" 15 "github.com/juju/utils/symlink" 16 gc "gopkg.in/check.v1" 17 18 "github.com/juju/juju/service/common" 19 "github.com/juju/juju/service/upstart" 20 coretesting "github.com/juju/juju/testing" 21 ) 22 23 func Test(t *testing.T) { gc.TestingT(t) } 24 25 type UpstartSuite struct { 26 coretesting.BaseSuite 27 testPath string 28 service *upstart.Service 29 initDir string 30 } 31 32 var _ = gc.Suite(&UpstartSuite{}) 33 34 func (s *UpstartSuite) SetUpTest(c *gc.C) { 35 s.testPath = c.MkDir() 36 s.initDir = c.MkDir() 37 s.PatchEnvPathPrepend(s.testPath) 38 s.PatchValue(&upstart.InstallStartRetryAttempts, utils.AttemptStrategy{}) 39 s.PatchValue(&upstart.InitDir, s.initDir) 40 s.service = upstart.NewService( 41 "some-service", 42 common.Conf{ 43 Desc: "some service", 44 Cmd: "some command", 45 }, 46 ) 47 } 48 49 var checkargs = ` 50 #!/bin/bash --norc 51 if [ "$1" != "--system" ]; then 52 exit 255 53 fi 54 if [ "$2" != "some-service" ]; then 55 exit 255 56 fi 57 if [ "$3" != "" ]; then 58 exit 255 59 fi 60 `[1:] 61 62 func (s *UpstartSuite) MakeTool(c *gc.C, name, script string) { 63 path := filepath.Join(s.testPath, name) 64 err := ioutil.WriteFile(path, []byte(checkargs+script), 0755) 65 c.Assert(err, jc.ErrorIsNil) 66 } 67 68 func (s *UpstartSuite) StoppedStatus(c *gc.C) { 69 s.MakeTool(c, "status", `echo "some-service stop/waiting"`) 70 } 71 72 func (s *UpstartSuite) RunningStatus(c *gc.C) { 73 s.MakeTool(c, "status", `echo "some-service start/running, process 123"`) 74 } 75 76 func (s *UpstartSuite) TestInitDir(c *gc.C) { 77 svc := upstart.NewService("blah", common.Conf{}) 78 c.Assert(svc.Conf.InitDir, gc.Equals, s.initDir) 79 } 80 81 func (s *UpstartSuite) goodInstall(c *gc.C) { 82 s.MakeTool(c, "start", "exit 0") 83 err := s.service.Install() 84 c.Assert(err, jc.ErrorIsNil) 85 } 86 87 func (s *UpstartSuite) TestInstalled(c *gc.C) { 88 c.Assert(s.service.Installed(), jc.IsFalse) 89 s.goodInstall(c) 90 c.Assert(s.service.Installed(), jc.IsTrue) 91 } 92 93 func (s *UpstartSuite) TestExists(c *gc.C) { 94 // Setup creates the file, but it is empty. 95 c.Assert(s.service.Exists(), jc.IsFalse) 96 s.goodInstall(c) 97 c.Assert(s.service.Exists(), jc.IsTrue) 98 } 99 100 func (s *UpstartSuite) TestExistsNonEmpty(c *gc.C) { 101 s.goodInstall(c) 102 s.service.Conf.Cmd = "something else" 103 c.Assert(s.service.Exists(), jc.IsFalse) 104 } 105 106 func (s *UpstartSuite) TestRunning(c *gc.C) { 107 s.MakeTool(c, "status", "exit 1") 108 c.Assert(s.service.Running(), jc.IsFalse) 109 s.MakeTool(c, "status", `echo "GIBBERISH NONSENSE"`) 110 c.Assert(s.service.Running(), jc.IsFalse) 111 s.RunningStatus(c) 112 c.Assert(s.service.Running(), jc.IsTrue) 113 } 114 115 func (s *UpstartSuite) TestStart(c *gc.C) { 116 s.RunningStatus(c) 117 s.MakeTool(c, "start", "exit 99") 118 c.Assert(s.service.Start(), gc.IsNil) 119 s.StoppedStatus(c) 120 c.Assert(s.service.Start(), gc.ErrorMatches, ".*exit status 99.*") 121 s.MakeTool(c, "start", "exit 0") 122 c.Assert(s.service.Start(), gc.IsNil) 123 } 124 125 func (s *UpstartSuite) TestStop(c *gc.C) { 126 s.StoppedStatus(c) 127 s.MakeTool(c, "stop", "exit 99") 128 c.Assert(s.service.Stop(), gc.IsNil) 129 s.RunningStatus(c) 130 c.Assert(s.service.Stop(), gc.ErrorMatches, ".*exit status 99.*") 131 s.MakeTool(c, "stop", "exit 0") 132 c.Assert(s.service.Stop(), gc.IsNil) 133 } 134 135 func (s *UpstartSuite) TestRemoveMissing(c *gc.C) { 136 c.Assert(s.service.StopAndRemove(), gc.IsNil) 137 } 138 139 func (s *UpstartSuite) TestRemoveStopped(c *gc.C) { 140 s.goodInstall(c) 141 s.StoppedStatus(c) 142 c.Assert(s.service.StopAndRemove(), gc.IsNil) 143 _, err := os.Stat(filepath.Join(s.service.Conf.InitDir, "some-service.conf")) 144 c.Assert(err, jc.Satisfies, os.IsNotExist) 145 } 146 147 func (s *UpstartSuite) TestRemoveRunning(c *gc.C) { 148 s.goodInstall(c) 149 s.RunningStatus(c) 150 s.MakeTool(c, "stop", "exit 99") 151 c.Assert(s.service.StopAndRemove(), gc.ErrorMatches, ".*exit status 99.*") 152 _, err := os.Stat(filepath.Join(s.service.Conf.InitDir, "some-service.conf")) 153 c.Assert(err, jc.ErrorIsNil) 154 s.MakeTool(c, "stop", "exit 0") 155 c.Assert(s.service.StopAndRemove(), gc.IsNil) 156 _, err = os.Stat(filepath.Join(s.service.Conf.InitDir, "some-service.conf")) 157 c.Assert(err, jc.Satisfies, os.IsNotExist) 158 } 159 160 func (s *UpstartSuite) TestStopAndRemove(c *gc.C) { 161 s.goodInstall(c) 162 s.RunningStatus(c) 163 s.MakeTool(c, "stop", "exit 99") 164 165 // StopAndRemove will fail, as it calls stop. 166 c.Assert(s.service.StopAndRemove(), gc.ErrorMatches, ".*exit status 99.*") 167 _, err := os.Stat(filepath.Join(s.service.Conf.InitDir, "some-service.conf")) 168 c.Assert(err, jc.ErrorIsNil) 169 170 // Plain old Remove will succeed. 171 c.Assert(s.service.Remove(), gc.IsNil) 172 _, err = os.Stat(filepath.Join(s.service.Conf.InitDir, "some-service.conf")) 173 c.Assert(err, jc.Satisfies, os.IsNotExist) 174 } 175 176 func (s *UpstartSuite) TestInstallErrors(c *gc.C) { 177 conf := common.Conf{} 178 check := func(msg string) { 179 c.Assert(s.service.Install(), gc.ErrorMatches, msg) 180 _, err := s.service.InstallCommands() 181 c.Assert(err, gc.ErrorMatches, msg) 182 } 183 s.service.Conf = conf 184 s.service.Name = "" 185 check("missing Name") 186 s.service.Name = "some-service" 187 check("missing InitDir") 188 s.service.Conf.InitDir = c.MkDir() 189 check("missing Desc") 190 s.service.Conf.Desc = "this is an upstart service" 191 check("missing Cmd") 192 } 193 194 const expectStart = `description "this is an upstart service" 195 author "Juju Team <juju@lists.ubuntu.com>" 196 start on runlevel [2345] 197 stop on runlevel [!2345] 198 respawn 199 normal exit 0 200 ` 201 202 func (s *UpstartSuite) dummyConf(c *gc.C) common.Conf { 203 return common.Conf{ 204 Desc: "this is an upstart service", 205 Cmd: "do something", 206 InitDir: s.initDir, 207 } 208 } 209 210 func (s *UpstartSuite) assertInstall(c *gc.C, conf common.Conf, expectEnd string) { 211 expectContent := expectStart + expectEnd 212 expectPath := filepath.Join(conf.InitDir, "some-service.conf") 213 214 s.service.Conf = conf 215 svc := s.service 216 cmds, err := s.service.InstallCommands() 217 c.Assert(err, jc.ErrorIsNil) 218 c.Assert(cmds, gc.DeepEquals, []string{ 219 "cat >> " + expectPath + " << 'EOF'\n" + expectContent + "EOF\n", 220 "start some-service", 221 }) 222 223 s.MakeTool(c, "start", "exit 99") 224 err = svc.Install() 225 c.Assert(err, gc.ErrorMatches, ".*exit status 99.*") 226 s.MakeTool(c, "start", "exit 0") 227 err = svc.Install() 228 c.Assert(err, jc.ErrorIsNil) 229 content, err := ioutil.ReadFile(expectPath) 230 c.Assert(err, jc.ErrorIsNil) 231 c.Assert(string(content), gc.Equals, expectContent) 232 } 233 234 func (s *UpstartSuite) TestInstallSimple(c *gc.C) { 235 conf := s.dummyConf(c) 236 s.assertInstall(c, conf, "\n\nscript\n\n\n exec do something\nend script\n") 237 } 238 239 func (s *UpstartSuite) TestInstallExtraScript(c *gc.C) { 240 conf := s.dummyConf(c) 241 conf.ExtraScript = "extra lines of script" 242 s.assertInstall(c, conf, "\n\nscript\nextra lines of script\n\n exec do something\nend script\n") 243 } 244 245 func (s *UpstartSuite) TestInstallOutput(c *gc.C) { 246 conf := s.dummyConf(c) 247 conf.Out = "/some/output/path" 248 s.assertInstall(c, conf, "\n\nscript\n\n\n # Ensure log files are properly protected\n touch /some/output/path\n chown syslog:syslog /some/output/path\n chmod 0600 /some/output/path\n\n exec do something >> /some/output/path 2>&1\nend script\n") 249 } 250 251 func (s *UpstartSuite) TestInstallEnv(c *gc.C) { 252 conf := s.dummyConf(c) 253 conf.Env = map[string]string{"FOO": "bar baz", "QUX": "ping pong"} 254 s.assertInstall(c, conf, `env FOO="bar baz" 255 env QUX="ping pong" 256 257 258 script 259 260 261 exec do something 262 end script 263 `) 264 } 265 266 func (s *UpstartSuite) TestInstallLimit(c *gc.C) { 267 conf := s.dummyConf(c) 268 conf.Limit = map[string]string{"nofile": "65000 65000", "nproc": "20000 20000"} 269 s.assertInstall(c, conf, ` 270 limit nofile 65000 65000 271 limit nproc 20000 20000 272 273 script 274 275 276 exec do something 277 end script 278 `) 279 } 280 281 func (s *UpstartSuite) TestInstallAlreadyRunning(c *gc.C) { 282 pathTo := func(name string) string { 283 return filepath.Join(s.testPath, name) 284 } 285 s.MakeTool(c, "status-stopped", `echo "some-service stop/waiting"`) 286 s.MakeTool(c, "status-started", `echo "some-service start/running, process 123"`) 287 s.MakeTool(c, "stop", fmt.Sprintf( 288 "rm %s; ln -s %s %s", 289 pathTo("status"), pathTo("status-stopped"), pathTo("status"), 290 )) 291 s.MakeTool(c, "start", fmt.Sprintf( 292 "rm %s; ln -s %s %s", 293 pathTo("status"), pathTo("status-started"), pathTo("status"), 294 )) 295 err := symlink.New(pathTo("status-started"), pathTo("status")) 296 c.Assert(err, jc.ErrorIsNil) 297 298 conf := s.dummyConf(c) 299 s.service.UpdateConfig(conf) 300 err = s.service.Install() 301 c.Assert(err, jc.ErrorIsNil) 302 c.Assert(s.service, jc.Satisfies, (*upstart.Service).Running) 303 }