19
"github.com/juju/juju/environs"
20
"github.com/juju/juju/environs/configstore"
21
"github.com/juju/juju/juju/osenv"
22
"github.com/juju/juju/state"
23
"github.com/juju/juju/agent"
24
"github.com/juju/juju/network"
25
"github.com/juju/juju/api"
26
"github.com/juju/names"
27
_ "github.com/juju/juju/provider/maas"
28
coretesting "github.com/juju/juju/testing"
29
jujutesting "github.com/juju/juju/juju/testing"
30
"github.com/juju/juju/testing/factory"
31
"github.com/juju/juju/version"
32
corecharm "gopkg.in/juju/charm.v4"
33
//corecharm "gopkg.in/juju/charm.v5/charmrepo" :24
34
"github.com/juju/juju/instance"
35
goyaml "gopkg.in/yaml.v1"
41
err := handleCommand(os.Args[1])
43
fmt.Println(err.Error())
49
coretesting.MgoTestPackage(t)
52
type processInfo struct {
59
func handleCommand(command string) error {
60
if command == "bootstrap" {
63
if command == "api-endpoints" {
66
if command == "api-info" {
69
if command == "destroy-environment" {
70
return destroyEnvironment()
72
return errors.New("command not found")
75
func bootstrap() error {
76
password, err := environmentPassword()
80
command := exec.Command(os.Args[0])
81
command.Env = os.Environ()
82
command.Env = append(command.Env, "ADMIN_PASSWORD=" + password)
83
stdout, err := command.StdoutPipe()
88
apiInfo, err := parseApiInfo(stdout)
92
dialOpts := api.DialOpts{
93
DialAddressInterval: 50 * time.Millisecond,
94
Timeout: 5 * time.Second,
95
RetryDelay: 2 * time.Second,
97
state, err := api.Open(apiInfo, dialOpts)
101
client := state.Client()
102
watcher, err := client.WatchAll()
106
deltas, err := watcher.Next()
110
for _, delta := range deltas {
111
entityId := delta.Entity.EntityId()
112
if entityId.Kind == "machine" {
113
machineId, _ := entityId.Id.(string)
114
if machineId == "0" {
119
return errors.New("invalid delta")
122
func apiEndpoints() error {
123
info, err := readProcessInfo()
127
fmt.Println(info.EndpointAddr)
131
func apiInfo() error {
132
info, err := readProcessInfo()
136
fmt.Printf("{\"environ-uuid\": \"%s\", \"state-servers\": [\"%s\"]}\n", info.Uuid, info.EndpointAddr)
140
func destroyEnvironment() error {
141
info, err := readProcessInfo()
145
fifoPath := filepath.Join(info.WorkDir, "fifo")
146
fd, err := os.OpenFile(fifoPath, os.O_APPEND|os.O_WRONLY, 0600)
151
_, err = fd.WriteString("destroy\n")
158
func environmentPassword() (string, error) {
159
jujuHome := os.Getenv("JUJU_HOME")
160
osenv.SetJujuHome(jujuHome)
161
environs, err := environs.ReadEnvirons(
162
filepath.Join(jujuHome, "environments.yaml"))
166
names := environs.Names()
167
config, err := environs.Config(names[0])
171
return config.AdminSecret(), nil
174
func parseApiInfo(stdout io.ReadCloser) (*api.Info, error) {
175
buffer := bufio.NewReader(stdout)
176
line, _, err := buffer.ReadLine()
181
environTag := names.NewEnvironTag(uuid)
182
line, _, err = buffer.ReadLine()
186
workDir := string(line)
187
store, err := configstore.NewDisk(workDir)
191
info, err := store.ReadInfo("dummyenv")
195
credentials := info.APICredentials()
196
endpoint := info.APIEndpoint()
197
//addresses := endpoint.Addresses :24
198
port, ok := info.BootstrapConfig()["api-port"].(int)
200
return nil, errors.New("Invalid api port")
202
addresses := []string{fmt.Sprintf("localhost:%d", port)}
203
apiInfo := &api.Info{
205
Tag: names.NewLocalUserTag(credentials.User),
206
Password: credentials.Password,
207
CACert: endpoint.CACert,
208
EnvironTag: environTag,
210
err = writeProcessInfo(&processInfo{
212
EndpointAddr: addresses[0],
221
func readProcessInfo() (*processInfo, error) {
222
infoPath := filepath.Join(os.Getenv("JUJU_HOME"), "fakejuju")
223
data, err := ioutil.ReadFile(infoPath)
227
info := &processInfo{}
228
err = goyaml.Unmarshal(data, info)
235
func writeProcessInfo(info *processInfo) error {
236
jujuHome := os.Getenv("JUJU_HOME")
237
infoPath := filepath.Join(jujuHome, "fakejuju")
238
caCertPath := filepath.Join(jujuHome, "cert.ca")
239
data, _ := goyaml.Marshal(info)
240
err := ioutil.WriteFile(infoPath, data, 0644)
244
return ioutil.WriteFile(caCertPath, []byte(info.CACert), 0644)
247
type FakeJujuSuite struct {
248
jujutesting.JujuConnSuite
251
machineStarted map[string]bool
256
var _ = gc.Suite(&FakeJujuSuite{})
258
func (s *FakeJujuSuite) SetUpTest(c *gc.C) {
259
s.JujuConnSuite.SetUpTest(c)
261
ports := s.APIState.APIHostPorts()
262
ports[0][0].NetworkName = "dummy-provider-network"
263
err := s.State.SetAPIHostPorts(ports)
264
c.Assert(err, gc.IsNil)
266
s.machineStarted = make(map[string]bool)
267
s.PatchValue(&corecharm.CacheDir, c.MkDir())
268
password := "dummy-password"
269
if os.Getenv("ADMIN_PASSWORD") != "" {
270
password = os.Getenv("ADMIN_PASSWORD")
272
_, err = s.State.AddUser("admin", "Admin", password, "dummy-admin")
273
c.Assert(err, gc.IsNil)
274
_, err = s.State.AddEnvironmentUser(
275
names.NewLocalUserTag("admin"), names.NewLocalUserTag("dummy-admin")) //, "Admin") :24
276
c.Assert(err, gc.IsNil)
278
// Create a machine to manage the environment.
279
stateServer := s.Factory.MakeMachine(c, &factory.MachineParams{
280
InstanceId: s.newInstanceId(),
281
Nonce: agent.BootstrapNonce,
282
Jobs: []state.MachineJob{state.JobManageEnviron, state.JobHostUnits},
285
c.Assert(stateServer.SetAgentVersion(version.Current), gc.IsNil)
286
//address := network.NewScopedAddress("127.0.0.1", network.ScopeCloudLocal) :24
287
address := network.NewAddress("127.0.0.1", network.ScopeCloudLocal)
288
c.Assert(stateServer.SetProviderAddresses(address), gc.IsNil)
289
c.Assert(stateServer.SetStatus(state.StatusStarted, "", nil), gc.IsNil)
290
_, err = stateServer.SetAgentPresence()
291
c.Assert(err, gc.IsNil)
293
err = stateServer.WaitAgentPresence(coretesting.LongWait)
294
c.Assert(err, gc.IsNil)
296
apiInfo := s.APIInfo(c)
297
//fmt.Println(apiInfo.Addrs[0])
298
jujuHome := osenv.JujuHome()
299
fmt.Println(apiInfo.EnvironTag.Id())
300
fmt.Println(jujuHome)
302
binPath := filepath.Join(jujuHome, "bin")
303
os.Mkdir(binPath, 0755)
304
fakeSSHData := []byte("#!/bin/sh\nsleep 1\n")
305
fakeSSHPath := filepath.Join(binPath, "ssh")
306
err = ioutil.WriteFile(fakeSSHPath, fakeSSHData, 0755)
307
c.Assert(err, gc.IsNil)
308
os.Setenv("PATH", binPath + ":" + os.Getenv("PATH"))
310
s.fifoPath = filepath.Join(jujuHome, "fifo")
311
syscall.Mknod(s.fifoPath, syscall.S_IFIFO|0666, 0)
314
logPath := filepath.Join(jujuHome, "fake-juju.log")
315
s.logFile, err = os.OpenFile(logPath, os.O_RDWR | os.O_CREATE | os.O_APPEND, 0666)
316
c.Assert(err, gc.IsNil)
318
log.SetOutput(s.logFile)
319
log.Println("Set up completed")
322
func (s *FakeJujuSuite) TearDownTest(c *gc.C) {
323
s.JujuConnSuite.TearDownTest(c)
327
func (s *FakeJujuSuite) TestStart(c *gc.C) {
328
watcher := s.State.Watch()
330
fd, err := os.Open(s.fifoPath)
331
c.Assert(err, gc.IsNil)
332
scanner := bufio.NewScanner(fd)
337
deltas, err := watcher.Next()
338
log.Println("Got deltas")
340
if err.Error() == "watcher was stopped" {
341
log.Println("Watcher stopped")
344
log.Println("Unexpected error", err.Error())
346
c.Assert(err, gc.IsNil)
347
for _, d := range deltas {
349
entityId := d.Entity.EntityId()
351
data, err := json.MarshalIndent(d.Entity, "", " ")
352
c.Assert(err, gc.IsNil)
357
log.Println("Processing delta", verb, entityId.Kind, string(data[:]))
359
if entityId.Kind == "machine" {
360
machineId, ok := entityId.Id.(string)
361
c.Assert(ok, gc.Equals, true)
362
c.Assert(s.handleAddMachine(machineId), gc.IsNil)
364
if entityId.Kind == "unit" {
365
unitId, ok := entityId.Id.(string)
366
c.Assert(ok, gc.Equals, true)
367
c.Assert(s.handleAddUnit(unitId), gc.IsNil)
369
log.Println("Done processing delta")
374
func (s *FakeJujuSuite) handleAddMachine(id string) error {
375
machine, err := s.State.Machine(id)
379
if instanceId, _ := machine.InstanceId(); instanceId == "" {
380
err = machine.SetProvisioned(s.newInstanceId(), agent.BootstrapNonce, nil)
384
//address := network.NewScopedAddress("127.0.0.1", network.ScopeCloudLocal) :24
385
//err = machine.SetProviderAddresses(address) :24
386
address := network.NewAddress("127.0.0.1", network.ScopeCloudLocal)
387
err = machine.SetProviderAddresses(address)
392
//status, _ := machine.Status() :24
393
status, _, _, _ := machine.Status()
394
//addresses := machine.Addresses()
395
//if status.Status == state.StatusPending { :24
396
if status == state.StatusPending {
397
if err = s.startMachine(machine); err != nil {
400
} else if status == state.StatusStarted {//&& len(addresses) > 0 {
401
if _, ok := s.machineStarted[id]; !ok {
402
s.machineStarted[id] = true
403
if err = s.startUnits(machine); err != nil {
411
func (s *FakeJujuSuite) handleAddUnit(id string) error {
412
log.Println("Handle unit", id)
413
unit, err := s.State.Unit(id)
417
machineId, err := unit.AssignedMachineId()
421
log.Println("Got machineId", machineId)
422
machine, err := s.State.Machine(machineId)
426
machineStatus, _, _, _ := machine.Status()
427
if machineStatus != state.StatusStarted {
430
log.Println("Machine started")
431
//status, _ := unit.Status() :24
432
status, _, _, _ := unit.Status()
433
// if status.Status != state.StatusActive { :24
434
if status != state.StatusActive {
435
log.Println("Start unit")
436
// time.Sleep(2 * time.Second)
437
if err = s.startUnit(unit); err != nil {
441
log.Println("Done handling unit")
445
func (s *FakeJujuSuite) startMachine(machine *state.Machine) error {
446
/*address := network.NewAddress("127.0.0.1", network.ScopeCloudLocal)
447
err := machine.SetAddresses(address)
451
time.Sleep(500 * time.Millisecond)
452
err := machine.SetStatus(state.StatusStarted, "", nil)
456
err = machine.SetAgentVersion(version.Current)
460
_, err = machine.SetAgentPresence()
465
err = machine.WaitAgentPresence(coretesting.LongWait)
472
func (s *FakeJujuSuite) startUnits(machine *state.Machine) error {
473
units, err := machine.Units()
477
for _, unit := range units {
478
//unitStatus, _ := unit.Status() :24
479
unitStatus, _, _, _ := unit.Status()
480
//if unitStatus.Status == state.StatusMaintenance { :24
481
if unitStatus != state.StatusActive {
482
if err = s.startUnit(unit); err != nil {
490
func (s *FakeJujuSuite) startUnit(unit *state.Unit) error {
491
err := unit.SetStatus(state.StatusActive, "", nil)
495
_, err = unit.SetAgentPresence()
500
err = unit.WaitAgentPresence(coretesting.LongWait)
508
func (s *FakeJujuSuite) newInstanceId() instance.Id {
510
return instance.Id(fmt.Sprintf("id-%d", s.instanceCount))