~ericsnowcurrently/fake-juju/upload-store-charm

« back to all changes in this revision

Viewing changes to 1.22.6/fake-juju.go

  • Committer: Landscape Builder
  • Author(s): Free Ekanayaka
  • Date: 2016-04-06 10:27:36 UTC
  • mfrom: (12.3.1 drop-old-juju-versions)
  • Revision ID: landscape_builder-20160406102736-m1qvmg1n2r1z3pfs
Merge drop-old-juju-versions [f=] [r=landscape-builder,ack] [a=Free Ekanayaka]
Trivial branch for dropping support for fake-juju versions that we don't use anymore in any branch (I checked 15.11, 16.03, production, staging, trunk).

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
package main
2
 
 
3
 
import (
4
 
        "fmt"
5
 
        "testing"
6
 
        gc "gopkg.in/check.v1"
7
 
        "os"
8
 
        "os/exec"
9
 
        "bufio"
10
 
        "time"
11
 
        "path/filepath"
12
 
        "syscall"
13
 
        "io"
14
 
        "io/ioutil"
15
 
        "errors"
16
 
        "log"
17
 
        "encoding/json"
18
 
 
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"
36
 
)
37
 
 
38
 
func main() {
39
 
        if len(os.Args) > 1 {
40
 
                code := 0
41
 
                err := handleCommand(os.Args[1])
42
 
                if err != nil {
43
 
                        fmt.Println(err.Error())
44
 
                        code = 1
45
 
                }
46
 
                os.Exit(code)
47
 
        }
48
 
        t := &testing.T{}
49
 
        coretesting.MgoTestPackage(t)
50
 
}
51
 
 
52
 
type processInfo struct {
53
 
        WorkDir string
54
 
        EndpointAddr string
55
 
        Uuid string
56
 
        CACert string
57
 
}
58
 
 
59
 
func handleCommand(command string) error {
60
 
        if command == "bootstrap" {
61
 
                return bootstrap()
62
 
        }
63
 
        if command == "api-endpoints" {
64
 
                return apiEndpoints()
65
 
        }
66
 
        if command == "api-info" {
67
 
                return apiInfo()
68
 
        }
69
 
        if command == "destroy-environment" {
70
 
                return destroyEnvironment()
71
 
        }
72
 
        return errors.New("command not found")
73
 
}
74
 
 
75
 
func bootstrap() error {
76
 
        password, err := environmentPassword()
77
 
        if err != nil {
78
 
                return err
79
 
        }
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()
84
 
        if err != nil {
85
 
                return err
86
 
        }
87
 
        command.Start() 
88
 
        apiInfo, err := parseApiInfo(stdout)
89
 
        if err != nil {
90
 
                return err
91
 
        }
92
 
        dialOpts := api.DialOpts{
93
 
                DialAddressInterval: 50 * time.Millisecond,
94
 
                Timeout:             5 * time.Second,
95
 
                RetryDelay:          2 * time.Second,
96
 
        }
97
 
        state, err := api.Open(apiInfo, dialOpts)
98
 
        if err != nil {
99
 
                return err
100
 
        }
101
 
        client := state.Client()
102
 
        watcher, err := client.WatchAll()
103
 
        if err != nil {
104
 
                return err
105
 
        }
106
 
        deltas, err := watcher.Next()
107
 
        if err != nil {
108
 
                return err
109
 
        }
110
 
        for _, delta := range deltas {
111
 
                entityId := delta.Entity.EntityId()
112
 
                if entityId.Kind == "machine" {
113
 
                        machineId, _ := entityId.Id.(string)
114
 
                        if machineId == "0" {
115
 
                                return nil
116
 
                        }
117
 
                }
118
 
        }
119
 
        return errors.New("invalid delta")
120
 
}
121
 
 
122
 
func apiEndpoints() error {
123
 
        info, err := readProcessInfo()
124
 
        if err != nil {
125
 
                return err
126
 
        }
127
 
        fmt.Println(info.EndpointAddr)
128
 
        return nil
129
 
}
130
 
 
131
 
func apiInfo() error {
132
 
        info, err := readProcessInfo()
133
 
        if err != nil {
134
 
                return err
135
 
        }
136
 
        fmt.Printf("{\"environ-uuid\": \"%s\", \"state-servers\": [\"%s\"]}\n", info.Uuid, info.EndpointAddr)
137
 
        return nil
138
 
}
139
 
 
140
 
func destroyEnvironment() error {
141
 
        info, err := readProcessInfo()
142
 
        if err != nil {
143
 
                return err
144
 
        }
145
 
        fifoPath := filepath.Join(info.WorkDir, "fifo")
146
 
        fd, err := os.OpenFile(fifoPath, os.O_APPEND|os.O_WRONLY, 0600)
147
 
        if err != nil {
148
 
                return err
149
 
        }
150
 
        defer fd.Close()
151
 
        _, err = fd.WriteString("destroy\n")
152
 
        if err != nil {
153
 
                return err
154
 
        }
155
 
        return nil
156
 
}
157
 
 
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"))
163
 
        if err != nil {
164
 
                return "", err
165
 
        }
166
 
        names := environs.Names()
167
 
        config, err := environs.Config(names[0])
168
 
        if err != nil {
169
 
                return "", err
170
 
        }
171
 
        return config.AdminSecret(), nil
172
 
}
173
 
 
174
 
func parseApiInfo(stdout io.ReadCloser) (*api.Info, error) {
175
 
        buffer := bufio.NewReader(stdout)
176
 
        line, _, err := buffer.ReadLine()
177
 
        if err != nil {
178
 
                return nil, err
179
 
        }
180
 
        uuid := string(line)
181
 
        environTag := names.NewEnvironTag(uuid)
182
 
        line, _, err = buffer.ReadLine()
183
 
        if err != nil {
184
 
                return nil, err
185
 
        }
186
 
        workDir := string(line)
187
 
        store, err := configstore.NewDisk(workDir)
188
 
        if err != nil {
189
 
                return nil, err
190
 
        }
191
 
        info, err := store.ReadInfo("dummyenv")
192
 
        if err != nil {
193
 
                return nil, err
194
 
        }
195
 
        credentials := info.APICredentials()
196
 
        endpoint := info.APIEndpoint()
197
 
        //addresses := endpoint.Addresses :24
198
 
        port, ok := info.BootstrapConfig()["api-port"].(int)
199
 
        if !ok {
200
 
                return nil, errors.New("Invalid api port")
201
 
        }
202
 
        addresses := []string{fmt.Sprintf("localhost:%d", port)}
203
 
        apiInfo := &api.Info{
204
 
                Addrs: addresses,
205
 
                Tag: names.NewLocalUserTag(credentials.User),
206
 
                Password: credentials.Password,
207
 
                CACert: endpoint.CACert,
208
 
                EnvironTag: environTag,
209
 
        }
210
 
        err = writeProcessInfo(&processInfo{
211
 
                WorkDir: workDir,
212
 
                EndpointAddr: addresses[0],
213
 
                Uuid: uuid,
214
 
        })
215
 
        if err != nil {
216
 
                return nil, err
217
 
        }
218
 
        return apiInfo, nil
219
 
}
220
 
 
221
 
func readProcessInfo() (*processInfo, error) {
222
 
        infoPath := filepath.Join(os.Getenv("JUJU_HOME"), "fakejuju")
223
 
        data, err := ioutil.ReadFile(infoPath)
224
 
        if err != nil {
225
 
                return nil, err
226
 
        }
227
 
        info := &processInfo{}
228
 
        err = goyaml.Unmarshal(data, info)
229
 
        if err != nil {
230
 
                return nil, err
231
 
        }
232
 
        return info, nil
233
 
}
234
 
 
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)
241
 
        if err != nil {
242
 
                return err
243
 
        }
244
 
        return ioutil.WriteFile(caCertPath, []byte(info.CACert), 0644)
245
 
}
246
 
 
247
 
type FakeJujuSuite struct {
248
 
        jujutesting.JujuConnSuite
249
 
 
250
 
        instanceCount int
251
 
        machineStarted map[string]bool
252
 
        fifoPath string
253
 
        logFile *os.File
254
 
}
255
 
 
256
 
var _ = gc.Suite(&FakeJujuSuite{})
257
 
 
258
 
func (s *FakeJujuSuite) SetUpTest(c *gc.C) {
259
 
        s.JujuConnSuite.SetUpTest(c)
260
 
 
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)
265
 
 
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")
271
 
        }
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)
277
 
 
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},
283
 
                Series: "trusty",
284
 
        })
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)
292
 
        s.State.StartSync()
293
 
        err = stateServer.WaitAgentPresence(coretesting.LongWait)
294
 
        c.Assert(err, gc.IsNil)
295
 
 
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)
301
 
 
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"))
309
 
 
310
 
        s.fifoPath = filepath.Join(jujuHome, "fifo")
311
 
        syscall.Mknod(s.fifoPath, syscall.S_IFIFO|0666, 0)
312
 
 
313
 
        // Logging
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)
317
 
 
318
 
        log.SetOutput(s.logFile)
319
 
        log.Println("Set up completed")
320
 
}
321
 
 
322
 
func (s *FakeJujuSuite) TearDownTest(c *gc.C) {
323
 
        s.JujuConnSuite.TearDownTest(c)
324
 
        s.logFile.Close()
325
 
}
326
 
 
327
 
func (s *FakeJujuSuite) TestStart(c *gc.C) {
328
 
        watcher := s.State.Watch()
329
 
        go func() {
330
 
                fd, err := os.Open(s.fifoPath)
331
 
                c.Assert(err, gc.IsNil)
332
 
                scanner := bufio.NewScanner(fd)
333
 
                scanner.Scan()
334
 
                watcher.Stop()
335
 
        }()
336
 
        for {
337
 
                deltas, err := watcher.Next()
338
 
                log.Println("Got deltas")
339
 
                if err != nil {
340
 
                        if err.Error() == "watcher was stopped" {
341
 
                                log.Println("Watcher stopped")
342
 
                                break
343
 
                        }
344
 
                        log.Println("Unexpected error", err.Error())
345
 
                }
346
 
                c.Assert(err, gc.IsNil)
347
 
                for _, d := range deltas {
348
 
 
349
 
                        entityId := d.Entity.EntityId()
350
 
 
351
 
                        data, err := json.MarshalIndent(d.Entity, "", "  ")
352
 
                        c.Assert(err, gc.IsNil)
353
 
                        verb := "change"
354
 
                        if d.Removed {
355
 
                                verb = "remove"
356
 
                        }
357
 
                        log.Println("Processing delta", verb, entityId.Kind, string(data[:]))
358
 
 
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)
363
 
                        }
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)
368
 
                        }
369
 
                        log.Println("Done processing delta")
370
 
                }
371
 
        }
372
 
}
373
 
 
374
 
func (s *FakeJujuSuite) handleAddMachine(id string) error  {
375
 
        machine, err := s.State.Machine(id)
376
 
        if err != nil {
377
 
                return err
378
 
        }
379
 
        if instanceId, _ := machine.InstanceId(); instanceId == "" {
380
 
                err = machine.SetProvisioned(s.newInstanceId(), agent.BootstrapNonce, nil)
381
 
                if err != nil {
382
 
                        return err
383
 
                }
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)
388
 
                if err != nil {
389
 
                        return err
390
 
                }
391
 
        }
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 {
398
 
                        return err
399
 
                }
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 {
404
 
                                return err
405
 
                        }
406
 
                }
407
 
        }
408
 
        return nil
409
 
}
410
 
 
411
 
func (s *FakeJujuSuite) handleAddUnit(id string) error  {
412
 
        log.Println("Handle unit", id)
413
 
        unit, err := s.State.Unit(id)
414
 
        if err != nil {
415
 
                return err
416
 
        }
417
 
        machineId, err := unit.AssignedMachineId()
418
 
        if err != nil {
419
 
                return nil
420
 
        }
421
 
        log.Println("Got machineId", machineId)
422
 
        machine, err := s.State.Machine(machineId)
423
 
        if err != nil {
424
 
                return err
425
 
        }
426
 
        machineStatus, _, _, _ := machine.Status()
427
 
        if machineStatus != state.StatusStarted {
428
 
                return nil
429
 
        }
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 {
438
 
                        return err
439
 
                }
440
 
        }
441
 
        log.Println("Done handling unit")
442
 
        return nil
443
 
}
444
 
 
445
 
func (s *FakeJujuSuite) startMachine(machine *state.Machine) error  {
446
 
        /*address := network.NewAddress("127.0.0.1", network.ScopeCloudLocal)
447
 
        err := machine.SetAddresses(address)
448
 
        if err != nil {
449
 
                return err
450
 
        }*/
451
 
        time.Sleep(500 * time.Millisecond)
452
 
        err := machine.SetStatus(state.StatusStarted, "", nil)
453
 
        if err != nil {
454
 
                return err
455
 
        }
456
 
        err = machine.SetAgentVersion(version.Current)
457
 
        if err != nil {
458
 
                return err
459
 
        }
460
 
        _, err = machine.SetAgentPresence()
461
 
        if err != nil {
462
 
                return err
463
 
        }
464
 
        s.State.StartSync()
465
 
        err = machine.WaitAgentPresence(coretesting.LongWait)
466
 
        if err != nil {
467
 
                return err
468
 
        }
469
 
        return nil
470
 
}
471
 
 
472
 
func (s *FakeJujuSuite) startUnits(machine *state.Machine) error  {
473
 
        units, err := machine.Units()
474
 
        if err != nil {
475
 
                return err
476
 
        }
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 {
483
 
                                return err
484
 
                        }
485
 
                }
486
 
        }
487
 
        return nil
488
 
}
489
 
 
490
 
func (s *FakeJujuSuite) startUnit(unit *state.Unit) error  {
491
 
        err := unit.SetStatus(state.StatusActive, "", nil)
492
 
        if err != nil {
493
 
                return err
494
 
        }
495
 
        _, err = unit.SetAgentPresence()
496
 
        if err != nil {
497
 
                return err
498
 
        }
499
 
        s.State.StartSync()
500
 
        err = unit.WaitAgentPresence(coretesting.LongWait)
501
 
        if err != nil {
502
 
                return err
503
 
        }
504
 
        return nil
505
 
}
506
 
 
507
 
 
508
 
func (s *FakeJujuSuite) newInstanceId() instance.Id {
509
 
        s.instanceCount += 1
510
 
        return instance.Id(fmt.Sprintf("id-%d", s.instanceCount))
511
 
}