toquen 2.0.2 → 2.0.3

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 833edeed8ec76c60048f4f5492c70824f2faefb1
4
- data.tar.gz: c2fb59966d84c4c5da4fc5acf4af62d83df3249d
3
+ metadata.gz: a28059029b69454a045b609eb532ee6ae6c915b5
4
+ data.tar.gz: 90b6749d1f029af3c84a5a0bc8d73d4412e0a266
5
5
  SHA512:
6
- metadata.gz: de3d318ee334a66cdd7bdc42ce37dc84f4d0fc47d5a4632223accf821f35002f81055fefa94b244962294e290e683e2c3fe6c709ad1fd071bf42e2fdbc46c142
7
- data.tar.gz: 0e7b0556f75f879d39fc6c56e6ee49c51dc1bec3f0af88ba15d092e0c27c9646f9d757605f6fe481eb5128b440326ea8208784f8e47e45560453eb9b072b5049
6
+ metadata.gz: dab2f916dea92ea6ea56bb0b70abd5b6429c84ba8d542529b79638b66bde3499cb4ea5459bd48b13657db7ac38b86a7390222828a5f6782dad63a0625561eb03
7
+ data.tar.gz: 3734a36573be44c2d0c6cea9883b9fff820a812b76058bdc75608c0f6c0bebc45db82c79eee3c09336e68cb334aa36a2432032ae00f130f7cea6de65d1970193
data/README.md CHANGED
@@ -96,13 +96,6 @@ cap update_nodes
96
96
  This will update the local node information cache as well as the capistrano stages.
97
97
 
98
98
  ## Additional Configuration
99
- If you want to use a different tag name (or you like commas as a delimiter) you can specify your own role extractor/setter by placing the following in either your Capfile or config/deploy.rb:
100
-
101
- ```ruby
102
- # these are the default - replace with your own
103
- Toquen.config.aws_roles_extractor = lambda { |inst| (inst.tags["MyRoles"] || "").split(",") }
104
- Toquen.config.aws_roles_setter = lambda { |ec2, inst, roles| ec2.tags.create(inst, 'Roles', :value => roles.sort.join(' ')) }
105
- ```
106
99
 
107
100
  By default, instance information is only pulled out of the default region (us-east-1), but you can specify mutiple alternative regions:
108
101
 
data/Rakefile CHANGED
@@ -1,9 +1,9 @@
1
- require "bundler/gem_tasks"
1
+ require 'bundler/gem_tasks'
2
2
  require 'rdoc/task'
3
3
 
4
- RDoc::Task.new("doc") { |rdoc|
5
- rdoc.title = "Toquen: Capistrano + AWS + Chef-Solo"
4
+ RDoc::Task.new('doc') do |rdoc|
5
+ rdoc.title = 'Toquen: Capistrano + AWS + Chef-Solo'
6
6
  rdoc.rdoc_dir = 'docs'
7
7
  rdoc.rdoc_files.include('README.md')
8
8
  rdoc.rdoc_files.include('lib/**/*.rb')
9
- }
9
+ end
@@ -1,22 +1,7 @@
1
- require "toquen/version"
2
- require "toquen/stunning"
3
- require "toquen/aws"
4
- require "toquen/local_writer"
5
- require "toquen/bootstrapper"
6
- require "toquen/capistrano"
7
- require "toquen/details_table"
8
-
9
- module Toquen
10
- class Config
11
- attr_accessor :aws_roles_extractor, :aws_roles_setter
12
-
13
- def initialize
14
- @aws_roles_extractor = lambda { |inst| (inst.tags["Roles"] || "").split }
15
- @aws_roles_setter = lambda { |ec2, inst, roles| ec2.tags.create(inst, 'Roles', :value => roles.sort.join(' ')) }
16
- end
17
- end
18
-
19
- def self.config
20
- @config ||= Config.new
21
- end
22
- end
1
+ require 'toquen/version'
2
+ require 'toquen/stunning'
3
+ require 'toquen/aws'
4
+ require 'toquen/local_writer'
5
+ require 'toquen/bootstrapper'
6
+ require 'toquen/capistrano'
7
+ require 'toquen/details_table'
@@ -1,5 +1,6 @@
1
- require 'aws'
1
+ require 'aws-sdk'
2
2
 
3
+ # Top level module namespace
3
4
  module Toquen
4
5
  def self.servers_with_role(role)
5
6
  Toquen::AWSProxy.new.server_details.select do |details|
@@ -7,109 +8,101 @@ module Toquen
7
8
  end
8
9
  end
9
10
 
11
+ # Class to handle all interaction with AWS
10
12
  class AWSProxy
11
13
  attr_reader :regions
12
14
 
13
15
  def initialize
14
- @key_id = fetch(:aws_access_key_id)
15
- @key = fetch(:aws_secret_access_key)
16
16
  @regions = fetch(:aws_regions, ['us-east-1'])
17
- AWS.config(:access_key_id => @key_id, :secret_access_key => @key)
17
+ key = fetch(:aws_access_key_id)
18
+ key_id = fetch(:aws_secret_access_key)
19
+ creds = Aws::Credentials.new(key, key_id)
20
+ Aws.config.update(credentials: creds) if creds.set?
18
21
  end
19
22
 
20
- def server_details
21
- filter @regions.map { |region| server_details_in(region) }.flatten
23
+ def server_details(running = true, regions = nil)
24
+ each_instance(running, regions) { |inst| extract_details(inst) }
22
25
  end
23
26
 
24
- def filter(details)
25
- details.select { |detail|
26
- not detail[:name].nil? and detail[:roles].length > 0
27
- }
27
+ def each_instance(running = true, regions = nil)
28
+ filters = []
29
+ filters << { name: 'instance-state-name', values: ['running'] } if running
30
+
31
+ results = []
32
+ (regions || @regions).each do |region|
33
+ resource = Aws::EC2::Resource.new(region: region)
34
+ results += resource.instances.map { |i| yield(i) }
35
+ end
36
+ results
28
37
  end
29
38
 
30
39
  def add_role(ivips, role)
31
- @regions.each do |region|
32
- AWS.config(:access_key_id => @key_id, :secret_access_key => @key, :region => region)
33
- ec2 = AWS::EC2.new
34
- ec2.instances.map do |i|
35
- if ivips.include? i.public_ip_address
36
- roles = Toquen.config.aws_roles_extractor.call(i)
37
- unless roles.include? role
38
- roles << role
39
- ec2.tags.create(i, 'Roles', :value => roles.uniq.sort.join(' '))
40
- end
41
- end
42
- end
40
+ each_instance do |i|
41
+ roles = extract_details(i)[:roles]
42
+ next unless !roles.include?(role) && ivips.include?(i.public_ip_address)
43
+ roles << role
44
+ tag = { key: 'Roles', value: roles.uniq.sort.join(' ') }
45
+ i.create_tags(tags: [tag])
43
46
  end
44
47
  end
45
48
 
46
49
  def remove_role(ivips, role)
47
- @regions.each do |region|
48
- AWS.config(:access_key_id => @key_id, :secret_access_key => @key, :region => region)
49
- ec2 = AWS::EC2.new
50
- ec2.instances.map do |i|
51
- if ivips.include? i.public_ip_address
52
- roles = Toquen.config.aws_roles_extractor.call(i)
53
- if roles.include? role
54
- roles = roles.reject { |r| r == role }
55
- Toquen.config.aws_roles_setter.call(ec2, i, roles.uniq)
56
- end
57
- end
58
- end
50
+ each_instance do |i|
51
+ roles = extract_details(i)[:roles]
52
+ next unless roles.include?(role) && ivips.include?(i.public_ip_address)
53
+ roles.reject! { |r| r == role }
54
+ tag = { key: 'Roles', value: roles.uniq.sort.join(' ') }
55
+ i.create_tags(tags: [tag])
59
56
  end
60
57
  end
61
58
 
62
59
  def get_security_groups(ids)
63
- result = []
64
60
  @regions.map do |region|
65
- AWS.config(:access_key_id => @key_id, :secret_access_key => @key, :region => region)
66
- AWS.memoize do
67
- ectwo = AWS::EC2.new
68
- ectwo.security_groups.each { |sg| result << sg if ids.include? sg.id }
69
- end
70
- end
71
- result
61
+ sgs = Aws::EC2::Resource.new(region: region).security_groups
62
+ sgs.select { |sg| ids.include? sg.group_id }
63
+ end.flatten
72
64
  end
73
65
 
74
66
  def authorize_ingress(secgroup, protocol, port, ip)
75
67
  # test if exists first
76
- return false if secgroup.ingress_ip_permissions.to_a.select { |p|
77
- p.protocol == protocol and p.port_range.include?(port) and p.ip_ranges.include?(ip)
78
- }.length > 0
68
+ return false unless secgroup.ip_permissions.to_a.select do |p|
69
+ port_match = ((p.from_port)..(p.to_port)).cover? port
70
+ ip_match = p.ip_ranges.map(&:cidr_ip).include?(ip)
71
+ p.ip_protocol == protocol && port_match && ip_match
72
+ end.empty?
79
73
 
80
- secgroup.authorize_ingress(protocol, port, ip)
74
+ secgroup.authorize_ingress(ip_protocol: protocol, from_port: port,
75
+ to_port: port, cidr_ip: ip)
81
76
  true
82
77
  end
83
78
 
84
79
  def revoke_ingress(secgroup, protocol, port, ip)
85
80
  # test if exists first
86
- return false unless secgroup.ingress_ip_permissions.to_a.select { |p|
87
- p.protocol == protocol and p.port_range.include?(port) and p.ip_ranges.include?(ip)
88
- }.length > 0
81
+ return false if secgroup.ip_permissions.to_a.select do |p|
82
+ port_match = ((p.from_port)..(p.to_port)).cover? port
83
+ ip_match = p.ip_ranges.map(&:cidr_ip).include?(ip)
84
+ p.ip_protocol == protocol && port_match && ip_match
85
+ end.empty?
89
86
 
90
- secgroup.revoke_ingress(protocol, port, ip)
87
+ secgroup.revoke_ingress(ip_protocol: protocol, from_port: port,
88
+ to_port: port, cidr_ip: ip)
91
89
  true
92
90
  end
93
91
 
94
- def server_details_in(region)
95
- AWS.config(:access_key_id => @key_id, :secret_access_key => @key, :region => region)
96
- AWS.memoize do
97
- AWS::EC2.new.instances.filter("instance-state-name", "running").map do |i|
98
- {
99
- :id => i.tags["Name"],
100
- :internal_ip => i.private_ip_address,
101
- :external_ip => i.public_ip_address,
102
- :name => i.tags["Name"],
103
- :roles => Toquen.config.aws_roles_extractor.call(i),
104
- :type => i.instance_type,
105
- :external_dns => i.public_dns_name,
106
- :internal_dns => i.private_dns_name,
107
- :security_groups => i.security_groups.to_a.map(&:id),
108
- :environment => i.tags["Environment"] || nil
109
- }
110
- end
111
- end
92
+ def extract_details(instance)
93
+ tags = instance.tags.each_with_object({}) { |t, h| h[t.key] = t.value }
94
+ {
95
+ id: tags['Name'],
96
+ name: tags['Name'],
97
+ type: instance.instance_type,
98
+ environment: tags['Environment'],
99
+ internal_ip: instance.private_ip_address,
100
+ external_ip: instance.public_ip_address,
101
+ external_dns: instance.public_dns_name,
102
+ internal_dns: instance.private_dns_name,
103
+ roles: tags.fetch('Roles', '').split,
104
+ security_groups: instance.security_groups.map(&:group_id)
105
+ }
112
106
  end
113
-
114
107
  end
115
108
  end
@@ -6,7 +6,7 @@ module Toquen
6
6
  # host is available via the binding
7
7
  hosttype = fetch(:hosttype, 'ubuntu')
8
8
  path = File.expand_path("../templates/#{hosttype}_bootstrap.erb", __FILE__)
9
- raise "Bootstrap process for #{hosttype} does not exist!" unless File.exists?(path)
9
+ raise "Bootstrap process for #{hosttype} does not exist!" unless File.exist?(path)
10
10
  user = fetch(:ssh_options)[:user]
11
11
  StringIO.new ERB.new(File.read(path)).result(binding)
12
12
  end
@@ -5,14 +5,14 @@ require 'json'
5
5
 
6
6
  set :chef_upload_location, -> { "/home/#{fetch(:ssh_options)[:user]}" }
7
7
 
8
- desc "update local cache of nodes and roles"
8
+ desc 'update local cache of nodes and roles'
9
9
  task :update_nodes do
10
10
  load Pathname.new fetch(:deploy_config_path, 'config/deploy.rb')
11
11
  roles = Hash.new([])
12
12
  servers = []
13
13
 
14
14
  aws = Toquen::AWSProxy.new
15
- aws.server_details.each do |details|
15
+ aws.server_details.reject { |d| d[:roles].empty? }.each do |details|
16
16
  details[:roles].each { |role| roles[role] += [details] }
17
17
  roles['all'] += [details]
18
18
  Toquen::LocalWriter.create_node details
@@ -26,7 +26,7 @@ task :update_nodes do
26
26
  Toquen::LocalWriter.superfluous_check!(servers, roles.keys)
27
27
  end
28
28
 
29
- desc "SSH into a specific server"
29
+ desc 'SSH into a specific server'
30
30
  task :ssh do
31
31
  hosts = []
32
32
  on roles(:all) do |host|
@@ -34,10 +34,10 @@ task :ssh do
34
34
  end
35
35
 
36
36
  run_locally do
37
- if hosts.length == 0
38
- warn "No server matched that role"
37
+ if hosts.empty?
38
+ warn 'No server matched that role'
39
39
  elsif hosts.length > 1
40
- warn "More than one server matched that role"
40
+ warn 'More than one server matched that role'
41
41
  else
42
42
  keys = fetch(:ssh_options)[:keys]
43
43
  keyoptions = keys.map { |key| "-i #{key}" }.join(' ')
@@ -48,11 +48,11 @@ task :ssh do
48
48
  end
49
49
  end
50
50
 
51
- desc "send up apps.json config file"
51
+ desc 'send up apps.json config file'
52
52
  task :update_appconfig do
53
- if File.exists?('config/apps.json')
53
+ if File.exist?('config/apps.json')
54
54
  apps = JSON.parse(File.read('config/apps.json'))
55
- config = { "_description" => "Dropped off by Toquen/Chef.", "servers" => [] }.merge(apps['default'] || {})
55
+ config = { '_description' => 'Dropped off by Toquen/Chef.', 'servers' => [] }.merge(apps['default'] || {})
56
56
  Dir.glob("#{fetch(:chef_nodes_path)}/*.json") do |fname|
57
57
  open(fname, 'r') { |f| config['servers'] << JSON.parse(f.read) }
58
58
  end
@@ -67,18 +67,18 @@ task :update_appconfig do
67
67
  appconfig.merge!(apps[host.properties.environment.to_s] || {})
68
68
  end
69
69
  debug "Uploading app config file to #{dest}"
70
- upload! StringIO.new(JSON.pretty_generate(appconfig)), "/tmp/apps.json"
70
+ upload! StringIO.new(JSON.pretty_generate(appconfig)), '/tmp/apps.json'
71
71
  sudo "mv /tmp/apps.json #{dest}"
72
72
  sudo "chmod 755 #{dest}"
73
73
  end
74
74
  else
75
- run_locally {
76
- error "No config/apps.json file found."
77
- }
75
+ run_locally do
76
+ error 'No config/apps.json file found.'
77
+ end
78
78
  end
79
79
  end
80
80
 
81
- desc "bootstrap a server so that it can run chef"
81
+ desc 'bootstrap a server so that it can run chef'
82
82
  task :bootstrap do
83
83
  on roles(:all), in: :parallel do |host|
84
84
  info "Bootstrapping #{host}..."
@@ -88,24 +88,24 @@ task :bootstrap do
88
88
  end
89
89
  end
90
90
 
91
- desc "Update cookbooks/data bags/roles on server"
91
+ desc 'Update cookbooks/data bags/roles on server'
92
92
  task :update_kitchen do
93
93
  kitchen = "#{fetch(:chef_upload_location)}/kitchen"
94
- lkitchen = "/tmp/toquen/kitchen"
94
+ lkitchen = '/tmp/toquen/kitchen'
95
95
  user = fetch(:ssh_options)[:user]
96
96
  keys = fetch(:ssh_options)[:keys]
97
97
 
98
98
  run_locally do
99
- info "Building kitchen locally..."
100
- execute :rm, "-rf", lkitchen
101
- execute :mkdir, "-p", lkitchen
102
- %W(cookbooks data_bags roles environments nodes).each do |dname|
99
+ info 'Building kitchen locally...'
100
+ execute :rm, '-rf', lkitchen
101
+ execute :mkdir, '-p', lkitchen
102
+ %w(cookbooks data_bags roles environments nodes).each do |dname|
103
103
  source = File.expand_path fetch("chef_#{dname}_path".intern)
104
- execute :ln, "-s", source, File.join(lkitchen, dname)
104
+ execute :ln, '-s', source, File.join(lkitchen, dname)
105
105
  end
106
106
  end
107
107
 
108
- open("#{lkitchen}/chef_config.rb", 'w') { |f|
108
+ open("#{lkitchen}/chef_config.rb", 'w') do |f|
109
109
  f.write("cookbook_path '#{kitchen}/cookbooks'\n")
110
110
  f.write("role_path '#{kitchen}/roles'\n")
111
111
  f.write("data_bag_path '#{kitchen}/data_bags'\n")
@@ -114,7 +114,7 @@ task :update_kitchen do
114
114
  f.write("log_level :#{fetch(:chef_log_level)}\n")
115
115
  f.write("cache_path '/tmp/chef_cache'\n")
116
116
  f.write("local_mode 'true'\n")
117
- }
117
+ end
118
118
 
119
119
  on roles(:all), in: :parallel do |host|
120
120
  sudo "chown -R #{user} #{fetch(:chef_upload_location)}"
@@ -126,7 +126,7 @@ task :update_kitchen do
126
126
  end
127
127
  end
128
128
 
129
- desc "Run chef for servers"
129
+ desc 'Run chef for servers'
130
130
  task :cook do
131
131
  on roles(:all), in: :parallel do |host|
132
132
  info "Chef is now cooking on #{host}..."
@@ -138,11 +138,11 @@ task :cook do
138
138
  end
139
139
  before :cook, :update_kitchen
140
140
 
141
- desc "Add given role to machines"
142
- task :add_role, :role do |t, args|
141
+ desc 'Add given role to machines'
142
+ task :add_role, :role do |_t, args|
143
143
  run_locally do
144
- if args[:role].nil? or args[:role].empty?
145
- error "You must give the role to add"
144
+ if args[:role].nil? || args[:role].empty?
145
+ error 'You must give the role to add'
146
146
  else
147
147
  aws = Toquen::AWSProxy.new
148
148
  aws.add_role roles(:all), args[:role]
@@ -150,11 +150,11 @@ task :add_role, :role do |t, args|
150
150
  end
151
151
  end
152
152
 
153
- desc "Remove given role from machines"
154
- task :remove_role, :role do |t, args|
153
+ desc 'Remove given role from machines'
154
+ task :remove_role, :role do |_t, args|
155
155
  run_locally do
156
- if args[:role].nil? or args[:role].empty?
157
- error "You must give the role to remove"
156
+ if args[:role].nil? || args[:role].empty?
157
+ error 'You must give the role to remove'
158
158
  else
159
159
  aws = Toquen::AWSProxy.new
160
160
  aws.remove_role roles(:all), args[:role]
@@ -162,102 +162,102 @@ task :remove_role, :role do |t, args|
162
162
  end
163
163
  end
164
164
 
165
- desc "Open a port of ingress to the current machine"
166
- task :open_port, :port do |t, args|
165
+ desc 'Open a port of ingress to the current machine'
166
+ task :open_port, :port do |_t, args|
167
167
  port = (args[:port] || 22).to_i
168
168
  run_locally do
169
169
  ivip = StunClient.get_ip
170
170
  if ivip.nil?
171
- error "Could not fetch internet visible IP of this host."
171
+ error 'Could not fetch internet visible IP of this host.'
172
172
  return
173
173
  end
174
174
 
175
175
  ivip = "#{ivip}/32"
176
176
  aws = Toquen::AWSProxy.new
177
177
  aws.get_security_groups(fetch(:filter)[:secgroups]).each do |sg|
178
- if aws.authorize_ingress sg, :tcp, port, ivip
179
- info "Opened port tcp:#{port} on security group '#{sg.name}' (#{sg.id}) to #{ivip}"
178
+ if aws.authorize_ingress sg, 'tcp', port, ivip
179
+ info "Opened port tcp:#{port} on security group '#{sg.group_name}' (#{sg.id}) to #{ivip}"
180
180
  else
181
- warn "Port tcp:#{port} in security group '#{sg.name}' (#{sg.id}) already open to #{ivip}"
181
+ warn "Port tcp:#{port} in security group '#{sg.group_name}' (#{sg.id}) already open to #{ivip}"
182
182
  end
183
183
  end
184
184
  end
185
185
  end
186
186
 
187
- desc "Close a port of ingress to the current machine"
188
- task :close_port, :port do |t, args|
187
+ desc 'Close a port of ingress to the current machine'
188
+ task :close_port, :port do |_t, args|
189
189
  port = (args[:port] || 22).to_i
190
190
  run_locally do
191
191
  ivip = StunClient.get_ip
192
192
  if ivip.nil?
193
- error "Could not fetch internet visible IP of this host."
193
+ error 'Could not fetch internet visible IP of this host.'
194
194
  return
195
195
  end
196
196
 
197
197
  ivip = "#{ivip}/32"
198
198
  aws = Toquen::AWSProxy.new
199
199
  aws.get_security_groups(fetch(:filter)[:secgroups]).each do |sg|
200
- if aws.revoke_ingress sg, :tcp, port, ivip
201
- info "Closed port tcp:#{port} on security group '#{sg.name}' (#{sg.id}) to #{ivip}"
200
+ if aws.revoke_ingress sg, 'tcp', port, ivip
201
+ info "Closed port tcp:#{port} on security group '#{sg.group_name}' (#{sg.id}) to #{ivip}"
202
202
  else
203
- warn "Port tcp:#{port} in security group '#{sg.name}' (#{sg.id}) already closed to #{ivip}"
203
+ warn "Port tcp:#{port} in security group '#{sg.group_name}' (#{sg.id}) already closed to #{ivip}"
204
204
  end
205
205
  end
206
206
  end
207
207
  end
208
208
 
209
- desc "Open SSH ingress to current machine"
209
+ desc 'Open SSH ingress to current machine'
210
210
  task :open_ssh do
211
- invoke "open_port", "22"
211
+ invoke 'open_port', '22'
212
212
  end
213
213
 
214
- desc "Close SSH ingress to current machine"
214
+ desc 'Close SSH ingress to current machine'
215
215
  task :close_ssh do
216
- invoke "close_port", "22"
216
+ invoke 'close_port', '22'
217
217
  end
218
218
 
219
- desc "install toquen capistrano setup to current directory"
219
+ desc 'install toquen capistrano setup to current directory'
220
220
  task :toquen_install do
221
- unless Dir.exists?('config')
222
- puts "Creating config directory..."
221
+ unless Dir.exist?('config')
222
+ puts 'Creating config directory...'
223
223
  Dir.mkdir('config')
224
224
  end
225
- unless Dir.exists?('config/deploy')
226
- puts "Creating config/deploy directory..."
225
+ unless Dir.exist?('config/deploy')
226
+ puts 'Creating config/deploy directory...'
227
227
  Dir.mkdir('config/deploy')
228
228
  end
229
- if not File.exists?('config/deploy.rb')
230
- puts "Initializing config/deploy.rb configuration file..."
231
- FileUtils.cp File.expand_path("../templates/deploy.rb", __FILE__), 'config/deploy.rb'
229
+ unless File.exist?('config/deploy.rb')
230
+ puts 'Initializing config/deploy.rb configuration file...'
231
+ FileUtils.cp File.expand_path('../templates/deploy.rb', __FILE__), 'config/deploy.rb'
232
232
  end
233
- gipath = File.expand_path("../templates/gitignore", __FILE__)
234
- if not File.exists?('.gitignore')
235
- puts "Initializing .gitignore file..."
233
+ gipath = File.expand_path('../templates/gitignore', __FILE__)
234
+ if !File.exist?('.gitignore')
235
+ puts 'Initializing .gitignore file...'
236
236
  FileUtils.cp gipath, '.gitignore'
237
237
  else
238
- puts "You already have a .gitignore, consider adding these files to it:"
238
+ puts 'You already have a .gitignore, consider adding these files to it:'
239
239
  puts File.read(gipath)
240
240
  end
241
241
  end
242
242
 
243
- desc "Show all information about EC2 instances"
243
+ desc 'Show all information about EC2 instances'
244
244
  task :details do
245
245
  filter_roles = Set.new fetch(:filter)[:roles]
246
246
  aws = Toquen::AWSProxy.new
247
247
  aws.regions.each do |region|
248
- instances = aws.server_details_in(region).reject do |instance|
249
- instance_roles = instance[:roles] + ["all", "server-#{instance[:name]}"]
248
+ instances = aws.server_details(true, [region]).reject do |instance|
249
+ instance_roles = instance[:roles] + ['all', "server-#{instance[:name]}"]
250
250
  (filter_roles.intersection instance_roles.to_set).empty?
251
251
  end
252
252
  Toquen::DetailsTable.new(instances, region).output unless instances.empty?
253
253
  end
254
254
  end
255
-
255
+
256
256
  module Capistrano
257
257
  module TaskEnhancements
258
- alias_method :original_default_tasks, :default_tasks
258
+ alias original_default_tasks default_tasks
259
259
  def default_tasks
260
- original_default_tasks + %w{toquen_install update_nodes}
260
+ original_default_tasks + %w(toquen_install update_nodes)
261
261
  end
262
262
  end
263
263
  end
@@ -3,7 +3,6 @@ require 'term/ansicolor'
3
3
 
4
4
  module Toquen
5
5
  class DetailsTable
6
-
7
6
  def initialize(instances, region)
8
7
  @instances = instances
9
8
  @region = region
@@ -12,14 +11,14 @@ module Toquen
12
11
 
13
12
  def output
14
13
  table = Terminal::Table.new(
15
- :style => {
16
- :border_x => "",
17
- :border_i => "",
18
- :border_y => ""
14
+ style: {
15
+ border_x: '',
16
+ border_i: '',
17
+ border_y: ''
19
18
  }
20
19
  )
21
20
  table.title = @color.bold { "Instances in #{@region}" }
22
- header = [ "Name", "Roles", "Env", "Public", "Private", "Type" ]
21
+ header = %w(Name Roles Env Public Private Type)
23
22
  table.add_row header.map { |h| @color.underline @color.bold h }
24
23
  @instances.each do |instance|
25
24
  table.add_row instance_to_row(instance)
@@ -30,10 +29,10 @@ module Toquen
30
29
  def instance_to_row(instance)
31
30
  [
32
31
  @color.green { instance[:name] },
33
- @color.yellow { instance[:roles].join(",") },
34
- @color.magenta { instance[:environment] || "" },
35
- instance[:external_dns].nil? ? "(N/A)" : @color.cyan(instance[:external_dns]) + " (#{instance[:external_ip]})",
36
- instance[:internal_dns].nil? ? "(N/A)" : @color.cyan(instance[:internal_dns]) + " (#{instance[:internal_ip]})",
32
+ @color.yellow { instance[:roles].join(',') },
33
+ @color.magenta { instance[:environment] || '' },
34
+ instance[:external_dns].nil? ? '(N/A)' : @color.cyan(instance[:external_dns]) + " (#{instance[:external_ip]})",
35
+ instance[:internal_dns].nil? ? '(N/A)' : @color.cyan(instance[:internal_dns]) + " (#{instance[:internal_ip]})",
37
36
  @color.red { instance[:type] }
38
37
  ]
39
38
  end
@@ -3,7 +3,7 @@ module Toquen
3
3
  def self.create_node(details)
4
4
  FileUtils.mkdir_p fetch(:chef_nodes_path)
5
5
  path = File.join(fetch(:chef_nodes_path), "#{details[:name]}.json")
6
- existing = File.exists?(path) ? JSON.parse(File.read(path)) : {}
6
+ existing = File.exist?(path) ? JSON.parse(File.read(path)) : {}
7
7
  open(path, 'w') do |f|
8
8
  node = {
9
9
  'name' => details[:name],
@@ -21,14 +21,14 @@ module Toquen
21
21
  f.write("# This file will be overwritten by toquen! Don't put anything here.\n")
22
22
  f.write("set :stage, '#{name}'.intern\n")
23
23
  secgroups = []
24
- servers.each { |details|
25
- rstring = (details[:roles] + [ "all", "server-#{details[:name]}" ]).join(' ')
24
+ servers.each do |details|
25
+ rstring = (details[:roles] + ['all', "server-#{details[:name]}"]).join(' ')
26
26
  f.write("server '#{details[:external_ip]}', ")
27
27
  f.write("roles: %w{#{rstring}}, ")
28
28
  f.write("environment: \"#{details[:environment]}\", ") unless details[:environment].nil?
29
29
  f.write("awsname: '#{details[:name]}'\n")
30
30
  secgroups += details[:security_groups]
31
- }
31
+ end
32
32
  secstring = secgroups.uniq.join(' ')
33
33
  f.write("set :filter, roles: %w{#{name}}, secgroups: %w{#{secstring}}\n")
34
34
  end
@@ -37,18 +37,18 @@ module Toquen
37
37
  def self.superfluous_check!(servers, roles)
38
38
  # check for superflous stages / data bag items and warn if found
39
39
  run_locally do
40
- Dir["#{fetch(:chef_data_bags_path)}/servers/*.json"].each { |path|
41
- unless servers.include? File.basename(path, ".json")
40
+ Dir["#{fetch(:chef_data_bags_path)}/servers/*.json"].each do |path|
41
+ unless servers.include? File.basename(path, '.json')
42
42
  warn "Data bag item #{path} does not represent an active server. You should delete it."
43
43
  end
44
- }
44
+ end
45
45
 
46
46
  stages = roles + servers.map { |n| "server-#{n}" }
47
- Dir["config/deploy/*.rb"].each { |path|
48
- unless stages.include? File.basename(path, ".rb")
47
+ Dir['config/deploy/*.rb'].each do |path|
48
+ unless stages.include? File.basename(path, '.rb')
49
49
  warn "Stage #{path} does not represent an active server. You should delete it."
50
50
  end
51
- }
51
+ end
52
52
  end
53
53
  end
54
54
  end
@@ -8,37 +8,35 @@ class StunClient
8
8
  end
9
9
 
10
10
  def get_ip
11
- begin
12
- Timeout::timeout(0.5) {
13
- socket = UDPSocket.new
14
- data = [0x0001,0].pack("nn") + Random.new.bytes(16)
15
- socket.send(data, 0, @host, @port)
16
- data, _ = socket.recvfrom(1000)
17
- type, length = data.unpack("nn")
11
+ Timeout.timeout(0.5) do
12
+ socket = UDPSocket.new
13
+ data = [0x0001, 0].pack('nn') + Random.new.bytes(16)
14
+ socket.send(data, 0, @host, @port)
15
+ data, = socket.recvfrom(1000)
16
+ type, length = data.unpack('nn')
18
17
 
19
- # if not a message binding response
20
- return nil unless type == 0x0101
18
+ # if not a message binding response
19
+ return nil unless type == 0x0101
21
20
 
22
- data = data[20..-1]
23
- while data.size > 0
24
- type, length = data.unpack("nn")
25
- # if attr type is ATTR_MAPPED_ADDRESS, return it
26
- if type == 0x0001
27
- values = data[4...4+length].unpack("CCnCCCC")
28
- return values[3..-1]*"."
29
- end
30
- data = data[4+length..-1]
21
+ data = data[20..-1]
22
+ until data.empty?
23
+ type, length = data.unpack('nn')
24
+ # if attr type is ATTR_MAPPED_ADDRESS, return it
25
+ if type == 0x0001
26
+ values = data[4...4 + length].unpack('CCnCCCC')
27
+ return values[3..-1] * '.'
31
28
  end
29
+ data = data[4 + length..-1]
30
+ end
32
31
 
33
- return nil
34
- }
35
- rescue Timeout::Error
36
32
  return nil
37
33
  end
34
+ rescue Timeout::Error
35
+ return nil
38
36
  end
39
37
 
40
38
  def self.get_ip
41
- servers = [["stun.l.google.com", 19302], ["stun.ekiga.net", 3478], ["stunserver.org", 3478]]
39
+ servers = [['stun.l.google.com', 19_302], ['stun.ekiga.net', 3478], ['stunserver.org', 3478]]
42
40
  servers.each do |host, port|
43
41
  ip = StunClient.new(host, port).get_ip
44
42
  return ip unless ip.nil?
@@ -7,7 +7,7 @@ set :aws_secret_access_key, nil
7
7
  # Set the location of your SSH key. You can give a list of files, but
8
8
  # the first key given will be the one used to upload your chef files to
9
9
  # each server.
10
- set :ssh_options, { :keys => ["./mykey.pem"], :user => "ubuntu" }
10
+ set :ssh_options, keys: ['./mykey.pem'], user: 'ubuntu'
11
11
 
12
12
  # Set the location of your cookbooks/data bags/roles/nodes for Chef
13
13
  set :chef_cookbooks_path, 'kitchen/cookbooks'
@@ -1,3 +1,3 @@
1
1
  module Toquen
2
- VERSION = "2.0.2"
2
+ VERSION = '2.0.3'.freeze
3
3
  end
@@ -4,22 +4,23 @@ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
4
  require 'toquen/version'
5
5
 
6
6
  Gem::Specification.new do |gem|
7
- gem.name = "toquen"
7
+ gem.name = 'toquen'
8
8
  gem.version = Toquen::VERSION
9
- gem.authors = ["Brian Muller"]
10
- gem.email = ["bamuller@gmail.com"]
11
- gem.description = "Toquen: Capistrano + AWS + Chef-Solo"
12
- gem.summary = "Toquen: Joins Capistrano + AWS + Chef-Solo into small devops ease"
13
- gem.homepage = "https://github.com/bmuller/toquen"
9
+ gem.authors = ['Brian Muller']
10
+ gem.email = ['bamuller@gmail.com']
11
+ gem.description = 'Toquen: Capistrano + AWS + Chef-Solo'
12
+ gem.summary = 'Toquen: Joins Capistrano + AWS + Chef-Solo into small devops ease'
13
+ gem.homepage = 'https://github.com/bmuller/toquen'
14
14
  gem.licenses = ['MIT']
15
-
16
- gem.files = `git ls-files`.split($/)
17
- gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
15
+
16
+ gem.files = `git ls-files`.split($INPUT_RECORD_SEPARATOR)
17
+ gem.executables = gem.files.grep(%r{^bin/}).map { |f| File.basename(f) }
18
18
  gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
19
- gem.require_paths = ["lib"]
19
+ gem.require_paths = ['lib']
20
20
  gem.add_dependency('capistrano', '~> 3.0', '>= 3.0.1')
21
- gem.add_dependency('aws-sdk', '~> 1')
22
- gem.add_dependency('terminal-table', '~> 1.6', '>= 1.6.0')
23
- gem.add_dependency('term-ansicolor', '~> 1.3', '>= 1.3.2')
24
- gem.add_development_dependency('rdoc', '~> 4.2', '>= 4.2.2')
21
+ gem.add_dependency('aws-sdk', '~> 2')
22
+ gem.add_dependency('terminal-table', '~> 1.6')
23
+ gem.add_dependency('term-ansicolor', '~> 1.3')
24
+ gem.add_development_dependency('rdoc', '~> 4.2')
25
+ gem.add_development_dependency('rubocop')
25
26
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: toquen
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.0.2
4
+ version: 2.0.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Brian Muller
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-07-14 00:00:00.000000000 Z
11
+ date: 2016-07-21 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: capistrano
@@ -36,14 +36,14 @@ dependencies:
36
36
  requirements:
37
37
  - - "~>"
38
38
  - !ruby/object:Gem::Version
39
- version: '1'
39
+ version: '2'
40
40
  type: :runtime
41
41
  prerelease: false
42
42
  version_requirements: !ruby/object:Gem::Requirement
43
43
  requirements:
44
44
  - - "~>"
45
45
  - !ruby/object:Gem::Version
46
- version: '1'
46
+ version: '2'
47
47
  - !ruby/object:Gem::Dependency
48
48
  name: terminal-table
49
49
  requirement: !ruby/object:Gem::Requirement
@@ -51,9 +51,6 @@ dependencies:
51
51
  - - "~>"
52
52
  - !ruby/object:Gem::Version
53
53
  version: '1.6'
54
- - - ">="
55
- - !ruby/object:Gem::Version
56
- version: 1.6.0
57
54
  type: :runtime
58
55
  prerelease: false
59
56
  version_requirements: !ruby/object:Gem::Requirement
@@ -61,9 +58,6 @@ dependencies:
61
58
  - - "~>"
62
59
  - !ruby/object:Gem::Version
63
60
  version: '1.6'
64
- - - ">="
65
- - !ruby/object:Gem::Version
66
- version: 1.6.0
67
61
  - !ruby/object:Gem::Dependency
68
62
  name: term-ansicolor
69
63
  requirement: !ruby/object:Gem::Requirement
@@ -71,9 +65,6 @@ dependencies:
71
65
  - - "~>"
72
66
  - !ruby/object:Gem::Version
73
67
  version: '1.3'
74
- - - ">="
75
- - !ruby/object:Gem::Version
76
- version: 1.3.2
77
68
  type: :runtime
78
69
  prerelease: false
79
70
  version_requirements: !ruby/object:Gem::Requirement
@@ -81,9 +72,6 @@ dependencies:
81
72
  - - "~>"
82
73
  - !ruby/object:Gem::Version
83
74
  version: '1.3'
84
- - - ">="
85
- - !ruby/object:Gem::Version
86
- version: 1.3.2
87
75
  - !ruby/object:Gem::Dependency
88
76
  name: rdoc
89
77
  requirement: !ruby/object:Gem::Requirement
@@ -91,9 +79,6 @@ dependencies:
91
79
  - - "~>"
92
80
  - !ruby/object:Gem::Version
93
81
  version: '4.2'
94
- - - ">="
95
- - !ruby/object:Gem::Version
96
- version: 4.2.2
97
82
  type: :development
98
83
  prerelease: false
99
84
  version_requirements: !ruby/object:Gem::Requirement
@@ -101,9 +86,20 @@ dependencies:
101
86
  - - "~>"
102
87
  - !ruby/object:Gem::Version
103
88
  version: '4.2'
89
+ - !ruby/object:Gem::Dependency
90
+ name: rubocop
91
+ requirement: !ruby/object:Gem::Requirement
92
+ requirements:
93
+ - - ">="
94
+ - !ruby/object:Gem::Version
95
+ version: '0'
96
+ type: :development
97
+ prerelease: false
98
+ version_requirements: !ruby/object:Gem::Requirement
99
+ requirements:
104
100
  - - ">="
105
101
  - !ruby/object:Gem::Version
106
- version: 4.2.2
102
+ version: '0'
107
103
  description: 'Toquen: Capistrano + AWS + Chef-Solo'
108
104
  email:
109
105
  - bamuller@gmail.com