Left: | ||
Right: |
LEFT | RIGHT |
---|---|
1 package dummy | 1 // The dummy provider implements an environment provider for testing |
2 | 2 // purposes, registered with environs under the name "dummy". |
3 import ( | |
4 » "bytes" | |
5 » "errors" | |
6 » "fmt" | |
7 » "io" | |
8 » "io/ioutil" | |
9 » "launchpad.net/juju/go/environs" | |
10 » "launchpad.net/juju/go/schema" | |
11 » "launchpad.net/juju/go/state" | |
12 » "sort" | |
13 » "strings" | |
14 » "sync" | |
15 ) | |
16 | |
17 type Operation struct { | |
18 » Kind OperationKind | |
19 » Env string | |
20 } | |
21 | |
22 // Operation represents an action on the dummy provider. | |
23 type OperationKind int | |
24 | |
25 const ( | |
26 » OpNone OperationKind = iota | |
27 » OpBootstrap | |
28 » OpDestroy | |
29 » OpStartInstance | |
30 » OpStopInstances | |
31 » OpPutFile | |
32 ) | |
33 | |
34 var kindNames = []string{ | |
35 » OpNone: "OpNone", | |
36 » OpBootstrap: "OpBootstrap", | |
37 » OpDestroy: "OpDestroy", | |
38 » OpStartInstance: "OpStartInstance", | |
39 » OpStopInstances: "OpStopInstances", | |
40 » OpPutFile: "OpPutFile", | |
41 } | |
42 | |
43 func (k OperationKind) String() string { | |
44 » return kindNames[k] | |
45 } | |
46 | |
47 // environProvider represents the dummy provider. There is only ever one | |
48 // instance of this type (providerInstance) | |
49 type environProvider struct { | |
50 » mu sync.Mutex | |
51 » state *environState | |
52 » ops chan<- Operation | |
53 } | |
54 | |
55 // environState represents the state of an environment. | |
56 // It can be shared between several environ values, | |
57 // so that a given environment can be opened several times. | |
58 type environState struct { | |
59 » mu sync.Mutex | |
60 » maxId int // maximum instance id allocated so far. | |
61 » insts map[string]*instance | |
62 » files map[string][]byte | |
63 » bootstrapped bool | |
64 } | |
65 | |
66 var providerInstance environProvider | |
67 | |
68 // discardOperations discards all Operations written to it. | |
69 var discardOperations chan<- Operation | |
70 | |
71 func init() { | |
72 » environs.RegisterProvider("dummy", &providerInstance) | |
73 | |
74 » // Prime the first ops channel, so that naive clients can use | |
75 » // the testing environment by simply importing it. | |
76 » c := make(chan Operation) | |
77 » go func() { | |
78 » » for _ = range c { | |
79 » » } | |
80 » }() | |
81 » discardOperations = c | |
82 » Reset(discardOperations, true) | |
83 } | |
84 | |
85 // Reset closes any previously registered operation channel, | |
86 // cleans the environment state, and registers c to receive | |
87 // notifications of operations performed on newly opened | |
88 // dummy environments. All opened environments after a Reset | |
89 // will share the same underlying state (instances, etc). | |
90 // If clean is true, this will be empty; otherwise | |
niemeyer
2012/05/17 01:08:42
This will be empty? That comment doesn't seem to m
rog
2012/05/17 11:43:33
will refactor as mentioned in cmd_test.go
| |
91 // it will remain the same as before. | |
92 //· | 3 //· |
93 // The configuration YAML for the testing environment | 4 // The configuration YAML for the testing environment |
94 // must specify a "zookeeper" property with a boolean | 5 // must specify a "zookeeper" property with a boolean |
95 // value. If this is true, a zookeeper instance will be started | 6 // value. If this is true, a zookeeper instance will be started |
96 // the first time StateInfo is called on a newly reset environment. | 7 // the first time StateInfo is called on a newly reset environment. |
97 // NOTE: ZooKeeper isn't actually being started yet. | 8 // NOTE: ZooKeeper isn't actually being started yet. |
98 //· | 9 //· |
99 // The configuration data also accepts a "broken" property | 10 // The configuration data also accepts a "broken" property |
100 // of type boolean. If this is non-empty, any operation | 11 // of type boolean. If this is non-empty, any operation |
101 // after the environment has been opened will return | 12 // after the environment has been opened will return |
102 // the error "broken environment", and will also log that. | 13 // the error "broken environment", and will also log that. |
103 //· | 14 //· |
104 // The DNS name of instances is the same as the Id, | 15 // The DNS name of instances is the same as the Id, |
105 // with ".dns" appended. | 16 // with ".dns" appended. |
106 func Reset(c chan<- Operation, clean bool) { | 17 package dummy |
107 » providerInstance.reset(c, clean) | 18 |
108 } | 19 import ( |
109 | 20 » "bytes" |
110 func (e *environProvider) reset(c chan<- Operation, clean bool) { | 21 » "errors" |
22 » "fmt" | |
23 » "io" | |
24 » "io/ioutil" | |
25 » "launchpad.net/juju/go/environs" | |
26 » "launchpad.net/juju/go/schema" | |
27 » "launchpad.net/juju/go/state" | |
28 » "sort" | |
29 » "strings" | |
30 » "sync" | |
31 ) | |
32 | |
33 type Operation struct { | |
34 » Kind OperationKind | |
35 » Env string | |
36 } | |
37 | |
38 // Operation represents an action on the dummy provider. | |
39 type OperationKind int | |
40 | |
41 const ( | |
42 » OpNone OperationKind = iota | |
43 » OpBootstrap | |
44 » OpDestroy | |
45 » OpStartInstance | |
46 » OpStopInstances | |
47 » OpPutFile | |
48 ) | |
49 | |
50 var kindNames = []string{ | |
51 » OpNone: "OpNone", | |
52 » OpBootstrap: "OpBootstrap", | |
53 » OpDestroy: "OpDestroy", | |
54 » OpStartInstance: "OpStartInstance", | |
55 » OpStopInstances: "OpStopInstances", | |
56 » OpPutFile: "OpPutFile", | |
57 } | |
58 | |
59 func (k OperationKind) String() string { | |
60 » return kindNames[k] | |
61 } | |
62 | |
63 // environProvider represents the dummy provider. There is only ever one | |
64 // instance of this type (providerInstance) | |
65 type environProvider struct { | |
66 » mu sync.Mutex | |
67 » state *environState | |
68 » ops chan<- Operation | |
69 } | |
70 | |
71 // environState represents the state of an environment. | |
72 // It can be shared between several environ values, | |
73 // so that a given environment can be opened several times. | |
74 type environState struct { | |
75 » mu sync.Mutex | |
76 » maxId int // maximum instance id allocated so far. | |
77 » insts map[string]*instance | |
78 » files map[string][]byte | |
79 » bootstrapped bool | |
80 } | |
81 | |
82 var providerInstance environProvider | |
83 | |
84 // discardOperations discards all Operations written to it. | |
85 var discardOperations chan<- Operation | |
86 | |
87 func init() { | |
88 » environs.RegisterProvider("dummy", &providerInstance) | |
89 | |
90 » // Prime the first ops channel, so that naive clients can use | |
91 » // the testing environment by simply importing it. | |
92 » c := make(chan Operation) | |
93 » go func() { | |
94 » » for _ = range c { | |
95 » » } | |
96 » }() | |
97 » discardOperations = c | |
98 » Reset() | |
99 } | |
100 | |
101 // Reset resets the entire dummy environment and forgets any registered | |
102 // operation listener. All opened environments after Reset will share | |
103 // the same underlying state. | |
104 func Reset() { | |
105 » e := &providerInstance | |
106 » e.mu.Lock() | |
107 » defer e.mu.Unlock() | |
108 » e.ops = discardOperations | |
109 » e.state = &environState{ | |
110 » » insts: make(map[string]*instance), | |
111 » » files: make(map[string][]byte), | |
112 » } | |
113 } | |
114 | |
115 // Listen closes the previously registered listener (if any), | |
116 // and if c is not nil registers it to receive notifications· | |
117 // of follow up operations in the environment. | |
118 func Listen(c chan<- Operation) { | |
119 » e := &providerInstance | |
111 e.mu.Lock() | 120 e.mu.Lock() |
112 defer e.mu.Unlock() | 121 defer e.mu.Unlock() |
113 if c == nil { | 122 if c == nil { |
114 c = discardOperations | 123 c = discardOperations |
115 } | 124 } |
116 » if ops := e.ops; ops != discardOperations && ops != nil { | 125 » if e.ops != discardOperations { |
117 » » close(ops) | 126 » » close(e.ops) |
118 } | 127 } |
119 e.ops = c | 128 e.ops = c |
120 | |
121 if clean { | |
122 e.state = &environState{ | |
123 insts: make(map[string]*instance), | |
124 files: make(map[string][]byte), | |
125 } | |
126 } | |
127 } | 129 } |
128 | 130 |
129 func (e *environProvider) ConfigChecker() schema.Checker { | 131 func (e *environProvider) ConfigChecker() schema.Checker { |
130 return schema.FieldMap( | 132 return schema.FieldMap( |
131 schema.Fields{ | 133 schema.Fields{ |
132 "type": schema.Const("dummy"), | 134 "type": schema.Const("dummy"), |
133 "zookeeper": schema.Const(false), // TODO | 135 "zookeeper": schema.Const(false), // TODO |
134 "broken": schema.Bool(), | 136 "broken": schema.Bool(), |
135 }, | 137 }, |
136 []string{ | 138 []string{ |
(...skipping 208 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
345 // it's closed. | 347 // it's closed. |
346 type notifyCloser struct { | 348 type notifyCloser struct { |
347 io.Reader | 349 io.Reader |
348 notify chan bool | 350 notify chan bool |
349 } | 351 } |
350 | 352 |
351 func (r *notifyCloser) Close() error { | 353 func (r *notifyCloser) Close() error { |
352 r.notify <- true | 354 r.notify <- true |
353 return nil | 355 return nil |
354 } | 356 } |
LEFT | RIGHT |