hawser 0.1.1 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/lib/hawser/baking-command.rb +17 -0
- data/lib/hawser/cluster.rb +15 -1
- data/lib/hawser/credentialing.rb +22 -7
- data/lib/hawser/servers.rb +24 -0
- data/lib/hawser/volumes.rb +102 -0
- metadata +8 -7
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f37eabe7ab5a93f7ac12ae94512c90d3d5f92b5b
|
4
|
+
data.tar.gz: 897451652af6a7277f9f993ea68edd25b51a1b08
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b3a8730daffd3c68e99eb12e3d6d3db06e505fb5181bb993b5e72e146b85073c05e068a49b0c562280e6928b782826d799bf0e1e23d868dc4daa6af89d036acd
|
7
|
+
data.tar.gz: 6b08518ebf9b91e8a670d5106b63e395dc8f43f8169904452d6a4928d2fa795fff00da35eda1ec6ecb4975479b1a57b5a46952000f598f869101a92c292efa2b
|
@@ -9,6 +9,13 @@ module Hawser
|
|
9
9
|
|
10
10
|
setting :region, "us-west-1"
|
11
11
|
|
12
|
+
setting :block_mappings, {
|
13
|
+
"ami" => "sda1",
|
14
|
+
"root" => "/dev/sda1",
|
15
|
+
"ephemeral0" => "sda2",
|
16
|
+
"swap" => "sda3"
|
17
|
+
}
|
18
|
+
|
12
19
|
dir(:ephemeral_dir, "mnt",
|
13
20
|
dir(:keyfile_dir, "keys",
|
14
21
|
path(:private_key, "pk.pem"),
|
@@ -56,6 +63,10 @@ module Hawser
|
|
56
63
|
bundle.options += ["-k", private_key.abspath ]
|
57
64
|
bundle.options += ["-c", certificate_file.abspath ]
|
58
65
|
bundle.options += ["--user", aws_account_id ]
|
66
|
+
bundle.options += ["--block-device-mapping", block_mappings.map do |name, dev|
|
67
|
+
"#{name}=#{dev}"
|
68
|
+
end.join(",")
|
69
|
+
]
|
59
70
|
|
60
71
|
bundle.options += ["--destination", ephemeral_dir.abspath ]
|
61
72
|
bundle.options += ["--prefix", prefix ]
|
@@ -79,6 +90,12 @@ module Hawser
|
|
79
90
|
register.options += ["--region", region]
|
80
91
|
register.options += ["--aws-access-key", access_key]
|
81
92
|
register.options += ["--aws-secret-key", secret_key]
|
93
|
+
}) &
|
94
|
+
(cmd("rm") {|rm|
|
95
|
+
rm.options = ["-rf", keyfile_dir.abspath]
|
96
|
+
}) &
|
97
|
+
(cmd("rm") {|rm|
|
98
|
+
rm.options = ["-f", File::join(ephemeral_dir.abspath, prefix || "no-such-file"), File::join(ephemeral_dir.abspath, prefix || "no-such-file") + ".part.*" ]
|
82
99
|
})
|
83
100
|
end
|
84
101
|
end
|
data/lib/hawser/cluster.rb
CHANGED
@@ -2,6 +2,7 @@ require 'mattock'
|
|
2
2
|
require 'hawser/credentialing'
|
3
3
|
require 'hawser/baking'
|
4
4
|
require 'hawser/servers'
|
5
|
+
require 'hawser/volumes'
|
5
6
|
|
6
7
|
module Hawser
|
7
8
|
# Represents a cluster of servers on AWS
|
@@ -47,12 +48,25 @@ module Hawser
|
|
47
48
|
creds.credentials.proxy_settings_to(servers)
|
48
49
|
end
|
49
50
|
|
51
|
+
Hawser::Volumes.new do |volumes|
|
52
|
+
copy_settings_to(volumes)
|
53
|
+
volumes.cluster_name = name
|
54
|
+
creds.copy_settings_to(volumes)
|
55
|
+
creds.credentials.proxy_settings_to(volumes)
|
56
|
+
end
|
57
|
+
|
50
58
|
namespace :baking do
|
51
|
-
task :
|
59
|
+
task :copy_key => "credentials:establish"
|
60
|
+
task :copy_cert => "credentials:establish"
|
52
61
|
end
|
53
62
|
|
54
63
|
namespace :servers do
|
55
64
|
task :list => "credentials:establish"
|
65
|
+
task :view => "credentials:establish"
|
66
|
+
end
|
67
|
+
|
68
|
+
namespace :volume do
|
69
|
+
task :clone => "credentials:establish"
|
56
70
|
end
|
57
71
|
|
58
72
|
desc "Make an AMI copy of the running instance at :target named :name"
|
data/lib/hawser/credentialing.rb
CHANGED
@@ -72,10 +72,11 @@ module Hawser
|
|
72
72
|
|
73
73
|
cert = OpenSSL::X509::Certificate.new
|
74
74
|
cert.version = 2
|
75
|
-
cert.serial =
|
75
|
+
cert.serial = OpenSSL::Random.random_bytes(16).each_byte.inject(0){|sum, byte| (sum << 8) + byte}
|
76
76
|
cert.public_key = key.public_key
|
77
77
|
cert.not_before = Time.now
|
78
78
|
cert.not_after = cert.not_before + self.cert.lifetime.total_seconds
|
79
|
+
cert.sign(key, OpenSSL::Digest::SHA256.new)
|
79
80
|
|
80
81
|
cert.to_pem
|
81
82
|
end
|
@@ -126,12 +127,21 @@ module Hawser
|
|
126
127
|
in_namespace do
|
127
128
|
directory user_dir.abspath
|
128
129
|
|
129
|
-
|
130
|
+
task :umask do
|
131
|
+
File::umask(0077)
|
132
|
+
end
|
133
|
+
|
134
|
+
file signing_cert.abspath => [:umask, signing_key.abspath] do |task|
|
135
|
+
require 'base64'
|
136
|
+
|
130
137
|
key = File::read(signing_key.abspath)
|
131
|
-
|
138
|
+
cert_pem = signing_cert_content(key)
|
139
|
+
File.open(task.name, "wb") do |file|
|
140
|
+
file.print cert_pem
|
141
|
+
end
|
132
142
|
end
|
133
143
|
|
134
|
-
file signing_key.abspath do |task|
|
144
|
+
file signing_key.abspath => :umask do |task|
|
135
145
|
File.write(task.name, signing_key_content)
|
136
146
|
end
|
137
147
|
|
@@ -141,14 +151,16 @@ module Hawser
|
|
141
151
|
end
|
142
152
|
end
|
143
153
|
|
144
|
-
task :store do
|
154
|
+
task :store => :umask do
|
145
155
|
require 'yaml'
|
146
156
|
|
157
|
+
puts "Storing credentialing info at #{config_yaml.abspath}"
|
147
158
|
File::open(config_yaml.abspath, "w") do |config|
|
148
159
|
config.write YAML.dump(Hash[credentials.to_hash.map do |key,value|
|
149
160
|
[key.to_s, value]
|
150
161
|
end])
|
151
162
|
end
|
163
|
+
|
152
164
|
end
|
153
165
|
|
154
166
|
task :iam => "get:access" do
|
@@ -160,9 +172,10 @@ module Hawser
|
|
160
172
|
end
|
161
173
|
|
162
174
|
namespace :get do
|
163
|
-
task :access => :load do
|
175
|
+
task :access => [:umask, :load] do
|
164
176
|
if credentials.access_key.nil? or credentials.secret_key.nil?
|
165
177
|
load_from_csv(File.read(creds_csv.abspath))
|
178
|
+
puts "Loaded access key id and key secret from CSV at #{creds_csv.abspath}"
|
166
179
|
end
|
167
180
|
end
|
168
181
|
|
@@ -181,11 +194,12 @@ module Hawser
|
|
181
194
|
namespace :set do
|
182
195
|
task :password => :iam_user do
|
183
196
|
unless credentials.password.nil?
|
197
|
+
puts "Setting login password"
|
184
198
|
iam_user.login_policy.password = credentials.password
|
185
199
|
end
|
186
200
|
end
|
187
201
|
|
188
|
-
task :certificate => [:iam_user, signing_cert.abspath, "get:certificate_id"] do
|
202
|
+
task :certificate => [:umask, :iam_user, signing_cert.abspath, "get:certificate_id"] do
|
189
203
|
if !credentials.certificate_id.nil?
|
190
204
|
begin
|
191
205
|
iam_user.signing_certificates[credentials.certificate_id].contents
|
@@ -194,6 +208,7 @@ module Hawser
|
|
194
208
|
end
|
195
209
|
end
|
196
210
|
|
211
|
+
puts "Uploading signing certificate at #{signing_cert.abspath}"
|
197
212
|
cert = iam_user.signing_certificates.upload(File::read(signing_cert.abspath))
|
198
213
|
credentials.certificate_id = cert.id
|
199
214
|
end
|
data/lib/hawser/servers.rb
CHANGED
@@ -31,6 +31,30 @@ module Hawser
|
|
31
31
|
"key_name" => instance.key_name }
|
32
32
|
end))
|
33
33
|
end
|
34
|
+
|
35
|
+
desc "View details for a server for #{cluster_name}"
|
36
|
+
task :view, [:id] do |task, args|
|
37
|
+
if args[:id].nil?
|
38
|
+
fail ":id is required"
|
39
|
+
end
|
40
|
+
require 'yaml'
|
41
|
+
ec2 = AWS::EC2.new(:region => region, :access_key_id => access_key, :secret_access_key => secret_key)
|
42
|
+
|
43
|
+
instance = ec2.instances.find do |inst|
|
44
|
+
inst.instance_id == args[:id]
|
45
|
+
end
|
46
|
+
|
47
|
+
if instance.nil?
|
48
|
+
fail "Couldn't find instance with id #{args[:id]} in #{ec2.instances.map{|inst| inst.instance_id}}"
|
49
|
+
end
|
50
|
+
|
51
|
+
require 'pp'
|
52
|
+
pp instance
|
53
|
+
pp instance.class.ancestors
|
54
|
+
puts instance.to_yaml
|
55
|
+
pp instance.block_device_mappings
|
56
|
+
|
57
|
+
end
|
34
58
|
end
|
35
59
|
end
|
36
60
|
end
|
@@ -0,0 +1,102 @@
|
|
1
|
+
require 'mattock'
|
2
|
+
require 'aws-sdk'
|
3
|
+
|
4
|
+
module Hawser
|
5
|
+
class Volumes < Mattock::Tasklib
|
6
|
+
default_namespace :volume
|
7
|
+
|
8
|
+
setting :cluster_name
|
9
|
+
setting :access_key
|
10
|
+
setting :secret_key
|
11
|
+
setting :region, "us-west-1"
|
12
|
+
|
13
|
+
def define
|
14
|
+
in_namespace do
|
15
|
+
desc "Clone <from_dev> on <from_instance> to <to_dev> on <to_instance>"
|
16
|
+
task :clone, [:from_instance, :from_dev, :to_instance, :to_dev] do |task, args|
|
17
|
+
missing = [:from_instance, :from_dev, :to_instance].find_all do |key|
|
18
|
+
args[key].nil?
|
19
|
+
end
|
20
|
+
|
21
|
+
unless missing.empty?
|
22
|
+
fail "Missing required arguments: #{missing.inspect}"
|
23
|
+
end
|
24
|
+
|
25
|
+
to_dev = args[:to_dev] || args[:from_dev]
|
26
|
+
|
27
|
+
ec2 = AWS::EC2.new(:region => region, :access_key_id => access_key, :secret_access_key => secret_key)
|
28
|
+
|
29
|
+
instances = ec2.instances
|
30
|
+
from_instance = instances.find do |inst|
|
31
|
+
inst.instance_id == args[:from_instance]
|
32
|
+
end
|
33
|
+
|
34
|
+
to_instance = instances.find do |inst|
|
35
|
+
inst.instance_id == args[:to_instance]
|
36
|
+
end
|
37
|
+
|
38
|
+
missing_instances = []
|
39
|
+
if from_instance.nil?
|
40
|
+
missing_instances << "Missing instance for #{args[:from_instance].inspect}"
|
41
|
+
end
|
42
|
+
if to_instance.nil?
|
43
|
+
missing_instances << "Missing instance for #{args[:to_instance].inspect}"
|
44
|
+
end
|
45
|
+
unless missing_instances.empty?
|
46
|
+
fail "Missing instances: #{missing_instances.join.inspect}"
|
47
|
+
end
|
48
|
+
|
49
|
+
require 'pp'
|
50
|
+
from_device = from_instance.block_devices.find do |dev|
|
51
|
+
dev[:device_name] == args[:from_dev]
|
52
|
+
end
|
53
|
+
unless from_device
|
54
|
+
fail "No device mapped to #{args[:from_instance]} on #{args[:from_dev]}"
|
55
|
+
end
|
56
|
+
|
57
|
+
if to_instance.block_devices.any?{|dev| dev[:device_name] == to_dev}
|
58
|
+
fail "A device is already mapped to #{args[:to_instance]} on #{to_dev}"
|
59
|
+
end
|
60
|
+
|
61
|
+
from_volume = ec2.volumes.find do |vol|
|
62
|
+
from_device[:ebs][:volume_id] == vol.id
|
63
|
+
end
|
64
|
+
|
65
|
+
unless from_volume
|
66
|
+
fail "No volume matches #{from_device[:ebs][:volume_id].inspect}"
|
67
|
+
end
|
68
|
+
|
69
|
+
snapshot_desc = from_volume.tags["Name"] || "From #{args[:from_instance]}:#{args[:from_dev]}"
|
70
|
+
|
71
|
+
intermediate_snapshot = from_volume.create_snapshot(snapshot_desc)
|
72
|
+
at_exit{ intermediate_snapshot.delete }
|
73
|
+
|
74
|
+
wait_for_status("intermediate snapshot", intermediate_snapshot, :completed)
|
75
|
+
|
76
|
+
new_volume = intermediate_snapshot.create_volume(to_instance.availability_zone)
|
77
|
+
|
78
|
+
wait_for_status("volume creation", new_volume, :available)
|
79
|
+
|
80
|
+
new_volume.attach_to(to_instance, to_dev)
|
81
|
+
|
82
|
+
wait_for_status("volume attachment", new_volume, :in_use)
|
83
|
+
|
84
|
+
puts "Done"
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
end
|
89
|
+
|
90
|
+
def wait_for_status(name, resource, goal)
|
91
|
+
puts "Waiting for #{name}"
|
92
|
+
until [goal, :error].include?(resource.status)
|
93
|
+
print "."
|
94
|
+
sleep 1
|
95
|
+
end
|
96
|
+
|
97
|
+
puts "\n #{name} complete. Status: #{resource.status.inspect}"
|
98
|
+
fail if resource.status != goal
|
99
|
+
end
|
100
|
+
|
101
|
+
end
|
102
|
+
end
|
metadata
CHANGED
@@ -1,29 +1,29 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: hawser
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Judson Lester
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2015-01-30 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: aws-sdk
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
|
-
- -
|
17
|
+
- - <
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: '0'
|
19
|
+
version: '2.0'
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
|
-
- -
|
24
|
+
- - <
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version: '0'
|
26
|
+
version: '2.0'
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: mattock
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
@@ -52,6 +52,7 @@ files:
|
|
52
52
|
- lib/hawser/servers.rb
|
53
53
|
- lib/hawser/baking-command.rb
|
54
54
|
- lib/hawser/baking.rb
|
55
|
+
- lib/hawser/volumes.rb
|
55
56
|
- spec/hawser_spec.rb
|
56
57
|
- spec_help/gem_test_suite.rb
|
57
58
|
homepage: http://nyarly.github.com/hawser
|
@@ -64,7 +65,7 @@ rdoc_options:
|
|
64
65
|
- --main
|
65
66
|
- doc/README
|
66
67
|
- --title
|
67
|
-
- hawser-0.
|
68
|
+
- hawser-0.2.0 Documentation
|
68
69
|
require_paths:
|
69
70
|
- lib/
|
70
71
|
required_ruby_version: !ruby/object:Gem::Requirement
|