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  }