toquen 2.0.2 → 2.0.3

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 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