guignol 0.3.9 → 0.3.10
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.travis.yml +4 -0
- data/Gemfile.lock +8 -8
- data/README.md +26 -12
- data/Rakefile +2 -0
- data/lib/guignol/commands/list.rb +17 -1
- data/lib/guignol/configuration.rb +32 -30
- data/lib/guignol/logger.rb +20 -18
- data/lib/guignol/models/instance.rb +5 -1
- data/lib/guignol/version.rb +2 -2
- data/spec/guignol/instance_spec.rb +43 -18
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 602a8585b6cfa0db283f93cdfba5b3cf3b83df95
|
4
|
+
data.tar.gz: 5612487338b4c8fc3fc38fd1faf281443568746c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: fbd093e9fc9047efc71bb618af7c5f87a6ee827509ef8f7aeb6aad2748fe91f98642628151e663a291d18cbb8ebf7a19ca4a956f9ec57bc053e222b6690cfecf
|
7
|
+
data.tar.gz: bf1dc14babf9a08fbdec9ef987a967756de7caa4f9fc3b4bb643b13401e0fc98f70d781ce08b259a864426bc38af66d88ec85bd184bb6972767f8c9eaac9de2f
|
data/.travis.yml
ADDED
data/Gemfile.lock
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
guignol (0.3.
|
4
|
+
guignol (0.3.10)
|
5
5
|
activesupport
|
6
6
|
fog (~> 1.12.0)
|
7
7
|
parallel (~> 0.6.2)
|
@@ -11,13 +11,13 @@ PATH
|
|
11
11
|
GEM
|
12
12
|
remote: https://rubygems.org/
|
13
13
|
specs:
|
14
|
-
activesupport (4.0.
|
14
|
+
activesupport (4.0.1)
|
15
15
|
i18n (~> 0.6, >= 0.6.4)
|
16
16
|
minitest (~> 4.2)
|
17
17
|
multi_json (~> 1.3)
|
18
18
|
thread_safe (~> 0.1)
|
19
19
|
tzinfo (~> 0.3.37)
|
20
|
-
atomic (1.1.
|
20
|
+
atomic (1.1.14)
|
21
21
|
builder (3.2.2)
|
22
22
|
coderay (1.0.9)
|
23
23
|
diff-lcs (1.2.4)
|
@@ -33,11 +33,11 @@ GEM
|
|
33
33
|
nokogiri (~> 1.5.0)
|
34
34
|
ruby-hmac
|
35
35
|
formatador (0.2.4)
|
36
|
-
i18n (0.6.
|
36
|
+
i18n (0.6.5)
|
37
37
|
method_source (0.8.1)
|
38
|
-
mime-types (1.
|
38
|
+
mime-types (1.25)
|
39
39
|
minitest (4.7.5)
|
40
|
-
multi_json (1.
|
40
|
+
multi_json (1.8.2)
|
41
41
|
net-scp (1.1.2)
|
42
42
|
net-ssh (>= 2.6.5)
|
43
43
|
net-ssh (2.6.8)
|
@@ -61,9 +61,9 @@ GEM
|
|
61
61
|
ruby-hmac (0.4.0)
|
62
62
|
slop (3.4.5)
|
63
63
|
thor (0.18.1)
|
64
|
-
thread_safe (0.1.
|
64
|
+
thread_safe (0.1.3)
|
65
65
|
atomic
|
66
|
-
tzinfo (0.3.
|
66
|
+
tzinfo (0.3.38)
|
67
67
|
uuidtools (2.1.4)
|
68
68
|
|
69
69
|
PLATFORMS
|
data/README.md
CHANGED
@@ -35,6 +35,20 @@ Start by setting up your `~/.fog`:
|
|
35
35
|
|
36
36
|
Alternatively you can pass crendentials for Guignol by setting the `AWS_SECRET_KEY_ID` and `AWS_SECRET_ACCESS_KEY` environment variables, or by setting `:aws_access_key_id` and `:aws_secret_access_key` in `guignol.yml` (see below).
|
37
37
|
|
38
|
+
## Listing instances
|
39
|
+
|
40
|
+
# list all instances available
|
41
|
+
guignol list
|
42
|
+
|
43
|
+
# list instances that match a particular pattern
|
44
|
+
guignol list web
|
45
|
+
|
46
|
+
# list instances with AWS identifiers
|
47
|
+
guignol list <pattern> --with-instance-ids
|
48
|
+
|
49
|
+
# list instance ids only in a format suitable for being passed to `xargs` or `elba`
|
50
|
+
guignol list <pattern> --porcelain
|
51
|
+
|
38
52
|
|
39
53
|
## Creating, starting and stopping machines
|
40
54
|
|
@@ -48,7 +62,7 @@ Each instance needs at least a name an a UUID (both will become tags on your
|
|
48
62
|
instance):
|
49
63
|
|
50
64
|
# ~/.guignol.yml
|
51
|
-
---
|
65
|
+
---
|
52
66
|
hello-world:
|
53
67
|
:uuid: AF123799-3F55-4F0B-8E58-87C67A5977BA
|
54
68
|
|
@@ -98,12 +112,12 @@ Yes, Guignol will also create and attach your EBS volumes when starting up insta
|
|
98
112
|
Just add a `:volumes` entry to your instance configuration:
|
99
113
|
|
100
114
|
:volumes:
|
101
|
-
|
115
|
+
fubar-swap:
|
102
116
|
:uuid: 9D5A278E-432C-41DB-9FB5-8AF5C1BD021F
|
103
117
|
:dev: /dev/sdf
|
104
118
|
:size: 4
|
105
119
|
:delete_on_termination: true
|
106
|
-
|
120
|
+
fubar-data:
|
107
121
|
:uuid: E180203F-9DE1-4C6A-B09B-33B2FAC8F36E
|
108
122
|
:dev: /dev/sdg
|
109
123
|
:size: 20
|
@@ -119,7 +133,7 @@ Note that Guignol does not delete volumes when tearing down instances.
|
|
119
133
|
## Optional instance configuration
|
120
134
|
|
121
135
|
- `:domain`
|
122
|
-
The machine's domain name. If specified, Guignol will setup a
|
136
|
+
The machine's domain name. If specified, Guignol will setup a
|
123
137
|
CNAME in Route53 mapping *name*.*domain* to your EC2 instance where it
|
124
138
|
starts it (and tear it down when stopping it.)
|
125
139
|
|
@@ -131,13 +145,13 @@ Note that Guignol does not delete volumes when tearing down instances.
|
|
131
145
|
|
132
146
|
- `:image_id`
|
133
147
|
The AMI to use when creating this instance. Defaults to whatever Amazon defaults it to.
|
134
|
-
|
148
|
+
|
135
149
|
- `:flavor_id`
|
136
150
|
The type of instance to start. Defaults to `t1.micro` (the one with a free tier).
|
137
|
-
|
151
|
+
|
138
152
|
- `:key_name`
|
139
153
|
The keypair to deploy to this instance. Default to not deploying any for security reasons (meaning you probably won't be able to log in if unset, depending on the AMI you're using).
|
140
|
-
|
154
|
+
|
141
155
|
- `:security_group_ids`
|
142
156
|
A list of security groups you want your instance to be a member of.
|
143
157
|
|
@@ -160,7 +174,7 @@ Guignol parses this setting through ERB, and lets your access the configuration
|
|
160
174
|
Possible use case:
|
161
175
|
|
162
176
|
# ~/.guignol.yml
|
163
|
-
---
|
177
|
+
---
|
164
178
|
hello-world:
|
165
179
|
:uuid: AF123799-3F55-4F0B-8E58-87C67A5977BA
|
166
180
|
:domain: example.com
|
@@ -195,7 +209,7 @@ You can direct logging to a file of your choice by setting `GUIGNOL_LOG`.
|
|
195
209
|
This one just contains 1 machine, `fubar.example.com.`
|
196
210
|
|
197
211
|
# ~/.guignol.yml
|
198
|
-
---
|
212
|
+
---
|
199
213
|
fubar:
|
200
214
|
:domain: example.com.
|
201
215
|
:uuid: 68C3C0C2-1BA3-465F-8626-E065E4EF9048
|
@@ -203,7 +217,7 @@ This one just contains 1 machine, `fubar.example.com.`
|
|
203
217
|
:image_id: ami-15f7c961
|
204
218
|
:flavor_id: m1.small
|
205
219
|
:key_name: john-doe
|
206
|
-
:security_group_ids:
|
220
|
+
:security_group_ids:
|
207
221
|
- sg-7e638abc
|
208
222
|
:volumes:
|
209
223
|
fubar-swap:
|
@@ -223,9 +237,9 @@ This one just contains 1 machine, `fubar.example.com.`
|
|
223
237
|
export LOGGING=YES
|
224
238
|
exec "$0" > /tmp/user_data.log 2>&1
|
225
239
|
fi
|
226
|
-
|
240
|
+
|
227
241
|
mkswap -f /dev/xvdf > /dev/null && swapon /dev/xvdf
|
228
|
-
|
242
|
+
|
229
243
|
mount_data() {
|
230
244
|
mount -t ext4 /dev/xvdg /mnt
|
231
245
|
}
|
data/Rakefile
CHANGED
@@ -2,9 +2,13 @@ require 'guignol/commands/base'
|
|
2
2
|
|
3
3
|
Guignol::Shell.class_eval do
|
4
4
|
desc 'list [PATTERNS]', 'List the status of all known instances'
|
5
|
+
|
6
|
+
option :porcelain, :type => :boolean, :aliases => %w(-p --elba -e)
|
7
|
+
option :with_instance_ids, :type => :boolean, :aliases => '-i'
|
8
|
+
|
5
9
|
def list(*patterns)
|
6
10
|
patterns.push('.*') if patterns.empty?
|
7
|
-
Guignol::Commands::List.new(patterns).run
|
11
|
+
Guignol::Commands::List.new(patterns, options).run
|
8
12
|
end
|
9
13
|
end
|
10
14
|
|
@@ -13,12 +17,24 @@ module Guignol::Commands
|
|
13
17
|
private
|
14
18
|
|
15
19
|
def run_on_server(instance, options = {})
|
20
|
+
return output_porcelain_instance_ids(instance) if options[:porcelain]
|
21
|
+
|
16
22
|
synchronize do
|
23
|
+
if options[:with_instance_ids]
|
24
|
+
id = "#{ instance.id || 'unknown'} "
|
25
|
+
shell.say id.ljust(@max_width)
|
26
|
+
end
|
27
|
+
|
17
28
|
shell.say instance.name.ljust(@max_width + 1)
|
18
29
|
shell.say instance.state, colorize(instance.state)
|
19
30
|
end
|
20
31
|
end
|
21
32
|
|
33
|
+
def output_porcelain_instance_ids(instance)
|
34
|
+
return unless instance.id
|
35
|
+
synchronize { shell.say "#{instance.id} " }
|
36
|
+
end
|
37
|
+
|
22
38
|
def before_run(configs, options = {})
|
23
39
|
@max_width = configs.keys.map(&:size).max
|
24
40
|
end
|
@@ -3,41 +3,43 @@ require 'active_support'
|
|
3
3
|
require 'active_support/core_ext/enumerable'
|
4
4
|
require 'guignol'
|
5
5
|
|
6
|
-
module Guignol
|
6
|
+
module Guignol
|
7
|
+
module Configuration
|
7
8
|
|
8
|
-
|
9
|
-
|
10
|
-
|
9
|
+
def configuration
|
10
|
+
@configuration ||= load_config_file
|
11
|
+
end
|
11
12
|
|
12
|
-
|
13
|
+
private
|
13
14
|
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
15
|
+
def config_file_path
|
16
|
+
@config_file_path ||= [
|
17
|
+
Pathname.new(ENV['GUIGNOL_YML'] || '/var/nonexistent'),
|
18
|
+
Pathname.new('guignol.yml'),
|
19
|
+
Pathname.new('config/guignol.yml'),
|
20
|
+
Pathname.new(ENV['HOME']).join('.guignol.yml')
|
21
|
+
].find(&:exist?)
|
22
|
+
end
|
22
23
|
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
24
|
+
# Load the config hash for the file, converting old (v0.2.0) Yaml config files.
|
25
|
+
def load_config_file
|
26
|
+
return {} if config_file_path.nil?
|
27
|
+
data = YAML.load(config_file_path.read)
|
28
|
+
return data unless data.kind_of?(Array)
|
29
|
+
|
30
|
+
# Convert the toplevel array to a hash. Same for arrays of volumes.
|
31
|
+
Guignol.logger.warn "Configuration file '#{config_file_path}' uses the old array format. Trying to load it."
|
32
|
+
raise "Instance config lacks :name" unless data.collect_key(:name).all?
|
33
|
+
result = data.index_by { |item| item.delete(:name) }
|
34
|
+
result.each_pair do |name, config|
|
35
|
+
next unless config[:volumes]
|
36
|
+
raise "Volume config lacks :name" unless config[:volumes].collect_key(:name).all?
|
37
|
+
config[:volumes] = config[:volumes].index_by { |item| item.delete(:name) }
|
38
|
+
end
|
39
|
+
|
40
|
+
return result
|
37
41
|
end
|
38
42
|
|
39
|
-
|
43
|
+
Guignol.extend(self)
|
40
44
|
end
|
41
|
-
|
42
|
-
Guignol.extend(self)
|
43
45
|
end
|
data/lib/guignol/logger.rb
CHANGED
@@ -1,29 +1,31 @@
|
|
1
1
|
require 'logger'
|
2
2
|
|
3
|
-
module Guignol
|
4
|
-
|
5
|
-
|
6
|
-
logger.
|
7
|
-
|
3
|
+
module Guignol
|
4
|
+
module Logger
|
5
|
+
def logger
|
6
|
+
@logger ||= ::Logger.new(logger_file).tap do |logger|
|
7
|
+
logger.progname = 'guignol'
|
8
|
+
logger.formatter = Formatter.new
|
9
|
+
end
|
8
10
|
end
|
9
|
-
end
|
10
11
|
|
11
12
|
|
12
|
-
|
13
|
+
private
|
13
14
|
|
14
|
-
|
15
|
-
|
15
|
+
class Formatter < ::Logger::Formatter
|
16
|
+
Format = "[%s] %s: %s\n"
|
16
17
|
|
17
|
-
|
18
|
-
|
18
|
+
def call(severity, time, progname, msg)
|
19
|
+
Format % [time.strftime('%F %T'), severity, msg2str(msg)]
|
20
|
+
end
|
19
21
|
end
|
20
|
-
end
|
21
22
|
|
22
23
|
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
24
|
+
def logger_file
|
25
|
+
return File.open(ENV['GUIGNOL_LOG'] ,'a') if ENV['GUIGNOL_LOG']
|
26
|
+
$stdout.tty? ? $stdout : File.open('/dev/null','w')
|
27
|
+
end
|
27
28
|
|
28
|
-
|
29
|
-
end
|
29
|
+
Guignol.extend(self)
|
30
|
+
end
|
31
|
+
end
|
@@ -159,6 +159,10 @@ module Guignol::Models
|
|
159
159
|
subject && subject.dns_name
|
160
160
|
end
|
161
161
|
|
162
|
+
def id
|
163
|
+
return nil unless subject && subject.respond_to?(:id)
|
164
|
+
subject.id
|
165
|
+
end
|
162
166
|
|
163
167
|
private
|
164
168
|
|
@@ -267,7 +271,7 @@ module Guignol::Models
|
|
267
271
|
|
268
272
|
|
269
273
|
|
270
|
-
# walks the connection for matching servers, return
|
274
|
+
# walks the connection for matching servers, return
|
271
275
|
# either the found server of nil
|
272
276
|
def find_subject
|
273
277
|
connection.servers.
|
data/lib/guignol/version.rb
CHANGED
@@ -9,11 +9,6 @@ describe Guignol::Models::Instance do
|
|
9
9
|
:uuid => '948DB8E9-A356-4F66-8857-165FBDF5A71F'
|
10
10
|
}}
|
11
11
|
|
12
|
-
before(:each) do
|
13
|
-
# connection = stub(:servers => [])
|
14
|
-
# Fog::Compute.stub(:new).and_return(connection)
|
15
|
-
end
|
16
|
-
|
17
12
|
describe '#initialize' do
|
18
13
|
it 'should require :uuid' do
|
19
14
|
options.delete :uuid
|
@@ -26,7 +21,7 @@ describe Guignol::Models::Instance do
|
|
26
21
|
end
|
27
22
|
|
28
23
|
it 'should pass with minimal options' do
|
29
|
-
subject
|
24
|
+
expect { subject }.to_not raise_error
|
30
25
|
end
|
31
26
|
|
32
27
|
it 'parses ERB in user data' do
|
@@ -36,16 +31,24 @@ describe Guignol::Models::Instance do
|
|
36
31
|
end
|
37
32
|
end
|
38
33
|
|
34
|
+
describe '#create' do
|
35
|
+
it 'set server tags' do
|
36
|
+
expected_tags = {'Name' => name, 'UUID' => options[:uuid]}
|
37
|
+
|
38
|
+
subject.connection.should_receive(:create_tags)
|
39
|
+
.with(anything, {'Domain' => nil}.merge(expected_tags))
|
40
|
+
.and_return(double(:status => 200))
|
39
41
|
|
40
|
-
|
41
|
-
|
42
|
-
it 'configures DNS properly'
|
43
|
-
end
|
42
|
+
subject.create
|
43
|
+
end
|
44
44
|
|
45
|
+
it "configures DNS properly" do
|
46
|
+
subject.should_receive(:update_dns)
|
47
|
+
subject.create
|
48
|
+
end
|
45
49
|
|
46
|
-
describe '#create' do
|
47
50
|
it 'should pass with minimal options' do
|
48
|
-
subject.create
|
51
|
+
expect { subject.create }.to_not raise_error
|
49
52
|
end
|
50
53
|
|
51
54
|
it 'does not break when providing an availibity zone' do
|
@@ -63,26 +66,48 @@ describe Guignol::Models::Instance do
|
|
63
66
|
it 'fails when existing volumes are in different zones'
|
64
67
|
|
65
68
|
it 'starts up the server'
|
66
|
-
|
67
|
-
it_should_behave_like 'server setup'
|
68
69
|
end
|
69
70
|
|
70
71
|
|
72
|
+
describe "#id" do
|
73
|
+
it "returns nil when there is no 'subject' (server)" do
|
74
|
+
instance = Guignol::Models::Instance.new(name, options)
|
75
|
+
instance.stub(:subject).and_return(nil)
|
76
|
+
|
77
|
+
instance.id.should be_nil
|
78
|
+
end
|
79
|
+
|
80
|
+
it "returns the id when 'subject' has no id" do
|
81
|
+
instance = Guignol::Models::Instance.new(name, options)
|
82
|
+
instance.stub(:subject).and_return(double)
|
83
|
+
|
84
|
+
instance.id.should be_nil
|
85
|
+
end
|
86
|
+
|
87
|
+
it "returns the id when 'subject' exists and has an id" do
|
88
|
+
instance = Guignol::Models::Instance.new(name, options)
|
89
|
+
instance.stub(:subject).and_return(double(:id => 'i-123456'))
|
90
|
+
|
91
|
+
instance.id.should == 'i-123456'
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
71
95
|
describe '#start' do
|
72
|
-
it_should_behave_like 'server setup'
|
73
96
|
|
74
97
|
it 'returns when the server does not exist' do
|
75
|
-
|
98
|
+
instance = Guignol::Models::Instance.new(name, options)
|
99
|
+
instance.stub(:subject).and_return(nil)
|
100
|
+
|
101
|
+
instance.start.should be_nil
|
76
102
|
end
|
77
103
|
|
78
104
|
it 'returns with a server marked as "running"'
|
79
|
-
|
80
105
|
end
|
81
106
|
|
82
107
|
|
83
108
|
describe '#destroy' do
|
84
109
|
it 'should pass with minimal options' do
|
85
|
-
subject.destroy
|
110
|
+
expect { subject.destroy }.to_not raise_error
|
86
111
|
end
|
87
112
|
end
|
88
113
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: guignol
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.3.
|
4
|
+
version: 0.3.10
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Julien Letessier
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2013-
|
11
|
+
date: 2013-11-18 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -162,6 +162,7 @@ files:
|
|
162
162
|
- .gitignore
|
163
163
|
- .rspec
|
164
164
|
- .ruby-version
|
165
|
+
- .travis.yml
|
165
166
|
- Gemfile
|
166
167
|
- Gemfile.lock
|
167
168
|
- LICENCE
|