OLD | NEW |
1 package main | 1 package main |
2 | 2 |
3 import ( | 3 import ( |
4 » "io/ioutil" | 4 » "fmt" |
5 . "launchpad.net/gocheck" | 5 . "launchpad.net/gocheck" |
6 "launchpad.net/juju-core/cmd" | 6 "launchpad.net/juju-core/cmd" |
| 7 "launchpad.net/juju-core/environs" |
7 "launchpad.net/juju-core/juju/testing" | 8 "launchpad.net/juju-core/juju/testing" |
8 "launchpad.net/juju-core/state" | 9 "launchpad.net/juju-core/state" |
9 "launchpad.net/juju-core/version" | 10 "launchpad.net/juju-core/version" |
10 "os" | |
11 "path/filepath" | |
12 "time" | 11 "time" |
13 ) | 12 ) |
14 | 13 |
15 type UnitSuite struct { | 14 type UnitSuite struct { |
16 testing.JujuConnSuite | 15 testing.JujuConnSuite |
17 } | 16 } |
18 | 17 |
19 var _ = Suite(&UnitSuite{}) | 18 var _ = Suite(&UnitSuite{}) |
20 | 19 |
21 func (s *UnitSuite) TestParseSuccess(c *C) { | 20 func (s *UnitSuite) TestParseSuccess(c *C) { |
(...skipping 24 matching lines...) Expand all Loading... |
46 } | 45 } |
47 } | 46 } |
48 | 47 |
49 func (s *UnitSuite) TestParseUnknown(c *C) { | 48 func (s *UnitSuite) TestParseUnknown(c *C) { |
50 uc := &UnitAgent{} | 49 uc := &UnitAgent{} |
51 err := ParseAgentCommand(uc, []string{"--unit-name", "wordpress/1", "thu
ndering typhoons"}) | 50 err := ParseAgentCommand(uc, []string{"--unit-name", "wordpress/1", "thu
ndering typhoons"}) |
52 c.Assert(err, ErrorMatches, `unrecognized args: \["thundering typhoons"\
]`) | 51 c.Assert(err, ErrorMatches, `unrecognized args: \["thundering typhoons"\
]`) |
53 } | 52 } |
54 | 53 |
55 func (s *UnitSuite) TestRunStop(c *C) { | 54 func (s *UnitSuite) TestRunStop(c *C) { |
56 » // Set up state. | 55 » a, unit, _ := s.newAgent(c) |
57 » ch := s.AddTestingCharm(c, "dummy") | |
58 » svc, err := s.Conn.AddService("dummy", ch) | |
59 » c.Assert(err, IsNil) | |
60 » unit, err := svc.AddUnit() | |
61 » c.Assert(err, IsNil) | |
62 | |
63 » // Set up local environment. | |
64 » dataDir := s.DataDir() | |
65 » vers := version.Current.String() | |
66 » toolsDir := filepath.Join(dataDir, "tools", vers) | |
67 » err = os.MkdirAll(toolsDir, 0755) | |
68 » c.Assert(err, IsNil) | |
69 » err = ioutil.WriteFile(filepath.Join(toolsDir, "jujuc"), nil, 0644) | |
70 » c.Assert(err, IsNil) | |
71 » toolsLink := filepath.Join(dataDir, "tools", "unit-dummy-0") | |
72 » err = os.Symlink(vers, toolsLink) | |
73 » c.Assert(err, IsNil) | |
74 | |
75 » // Run a unit agent. | |
76 » a := &UnitAgent{ | |
77 » » Conf: AgentConf{dataDir, *s.StateInfo(c)}, | |
78 » » UnitName: unit.Name(), | |
79 » } | |
80 done := make(chan error) | 56 done := make(chan error) |
81 go func() { | 57 go func() { |
82 done <- a.Run(nil) | 58 done <- a.Run(nil) |
83 }() | 59 }() |
84 defer a.Stop() | 60 defer a.Stop() |
85 timeout := time.After(5 * time.Second) | 61 timeout := time.After(5 * time.Second) |
86 for { | 62 for { |
87 select { | 63 select { |
88 case <-timeout: | 64 case <-timeout: |
89 c.Fatalf("no activity detected") | 65 c.Fatalf("no activity detected") |
90 case <-time.After(50 * time.Millisecond): | 66 case <-time.After(50 * time.Millisecond): |
91 st, info, err := unit.Status() | 67 st, info, err := unit.Status() |
92 c.Assert(err, IsNil) | 68 c.Assert(err, IsNil) |
93 switch st { | 69 switch st { |
94 case state.UnitPending, state.UnitInstalled: | 70 case state.UnitPending, state.UnitInstalled: |
95 c.Logf("waiting...") | 71 c.Logf("waiting...") |
96 continue | 72 continue |
97 case state.UnitStarted: | 73 case state.UnitStarted: |
98 c.Logf("started!") | 74 c.Logf("started!") |
99 case state.UnitDown: | 75 case state.UnitDown: |
100 s.State.StartSync() | 76 s.State.StartSync() |
101 c.Logf("unit is still down") | 77 c.Logf("unit is still down") |
102 default: | 78 default: |
103 c.Fatalf("unexpected status %s %s", st, info) | 79 c.Fatalf("unexpected status %s %s", st, info) |
104 } | 80 } |
105 } | 81 } |
106 break | 82 break |
107 } | 83 } |
108 » err = a.Stop() | 84 » err := a.Stop() |
109 c.Assert(err, IsNil) | 85 c.Assert(err, IsNil) |
110 c.Assert(<-done, IsNil) | 86 c.Assert(<-done, IsNil) |
111 } | 87 } |
| 88 |
| 89 // newAgent starts a new unit agent running a unit |
| 90 // of the dummy charm. |
| 91 func (s *UnitSuite) newAgent(c *C) (*UnitAgent, *state.Unit, *state.Tools) { |
| 92 ch := s.AddTestingCharm(c, "dummy") |
| 93 svc, err := s.Conn.AddService("dummy", ch) |
| 94 c.Assert(err, IsNil) |
| 95 unit, err := svc.AddUnit() |
| 96 c.Assert(err, IsNil) |
| 97 |
| 98 dataDir, tools := primeTools(c, s.Conn, version.Current) |
| 99 tools1, err := environs.ChangeAgentTools(dataDir, unit.PathKey(), versio
n.Current) |
| 100 c.Assert(err, IsNil) |
| 101 c.Assert(tools1, DeepEquals, tools) |
| 102 |
| 103 return &UnitAgent{ |
| 104 Conf: AgentConf{dataDir, *s.StateInfo(c)}, |
| 105 UnitName: unit.Name(), |
| 106 }, unit, tools |
| 107 } |
| 108 |
| 109 func (s *UnitSuite) TestUpgrade(c *C) { |
| 110 newVers := version.Current |
| 111 newVers.Patch++ |
| 112 newTools := uploadTools(c, s.Conn, newVers) |
| 113 proposeVersion(c, s.State, newVers.Number, true) |
| 114 a, _, currentTools := s.newAgent(c) |
| 115 defer a.Stop() |
| 116 err := runWithTimeout(a) |
| 117 c.Assert(err, FitsTypeOf, &UpgradeReadyError{}) |
| 118 ug := err.(*UpgradeReadyError) |
| 119 c.Assert(ug.NewTools, DeepEquals, newTools) |
| 120 c.Assert(ug.OldTools, DeepEquals, currentTools) |
| 121 } |
| 122 |
| 123 func (s *UnitSuite) TestWithDeadUnit(c *C) { |
| 124 ch := s.AddTestingCharm(c, "dummy") |
| 125 svc, err := s.Conn.AddService("dummy", ch) |
| 126 c.Assert(err, IsNil) |
| 127 unit, err := svc.AddUnit() |
| 128 c.Assert(err, IsNil) |
| 129 err = unit.EnsureDead() |
| 130 c.Assert(err, IsNil) |
| 131 |
| 132 dataDir := c.MkDir() |
| 133 a := &UnitAgent{ |
| 134 Conf: AgentConf{dataDir, *s.StateInfo(c)}, |
| 135 UnitName: unit.Name(), |
| 136 } |
| 137 err = runWithTimeout(a) |
| 138 c.Assert(err, IsNil) |
| 139 |
| 140 // try again when the unit has been removed. |
| 141 err = svc.RemoveUnit(unit) |
| 142 c.Assert(err, IsNil) |
| 143 a = &UnitAgent{ |
| 144 Conf: AgentConf{dataDir, *s.StateInfo(c)}, |
| 145 UnitName: unit.Name(), |
| 146 } |
| 147 err = runWithTimeout(a) |
| 148 c.Assert(err, IsNil) |
| 149 } |
| 150 |
| 151 type runner interface { |
| 152 Run(*cmd.Context) error |
| 153 Stop() error |
| 154 } |
| 155 |
| 156 func runWithTimeout(runner runner) error { |
| 157 done := make(chan error) |
| 158 go func() { |
| 159 done <- runner.Run(nil) |
| 160 }() |
| 161 select { |
| 162 case err := <-done: |
| 163 return err |
| 164 case <-time.After(5 * time.Second): |
| 165 } |
| 166 err := runner.Stop() |
| 167 return fmt.Errorf("timed out waiting for agent to finish; stop error: %v
", err) |
| 168 } |
OLD | NEW |