miam 0.1.1 → 0.1.2

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: dac584f8c0f3829974bbf66a703a0514b0bba56b
4
- data.tar.gz: 4c1554986b97d252d2e6fea8c17dbdee4e7c0072
3
+ metadata.gz: 959a0bf3fb3d32d91bebccb4cb858b7ab9be503f
4
+ data.tar.gz: a31ededb7c84f9d188e15f9c19a20defbbbfcca8
5
5
  SHA512:
6
- metadata.gz: a197de1545bb2bfdaa906a215d23e61eb4ff63759875929a6f01605a38c6a3c4d5bd3dfa753a6e77af7c4521e0ef5f22ac36a70c1d049c8ada9e4a211f969601
7
- data.tar.gz: cad4724a8a76be2bfc6c92ebc5ef97bf95a5e2b08f97469ce2f1213b95cc8ac42c89d694d71cf2805b3ce7e93258a3212354e076455a1852351c81e1a1bb9c59
6
+ metadata.gz: f2ed7296253deed56af8e3c2e4628772a6c84691c078e655b1a9a95d58b5e201c68fc0817b71c1212927c16b9ade6383edeaa65832560dbdab07863a05970a6a
7
+ data.tar.gz: 8be72aa39cbd4bc73c27ae1ed75e8b5c74e367996c2933a76e00e8e21b478b2d9c829348b6786043b87420e5de648ad1a56f64c6f13b5ae4becbe50411768124
data/README.md CHANGED
@@ -52,6 +52,8 @@ Usage: miam [options]
52
52
  -e, --export
53
53
  -o, --output FILE
54
54
  --split
55
+ --split-more
56
+ --export-concurrency N
55
57
  --no-color
56
58
  --no-progress
57
59
  --debug
data/bin/miam CHANGED
@@ -2,6 +2,7 @@
2
2
  $: << File.expand_path("#{File.dirname __FILE__}/../lib")
3
3
  require 'rubygems'
4
4
  require 'miam'
5
+ require 'fileutils'
5
6
  require 'optparse'
6
7
 
7
8
  Version = Miam::VERSION
@@ -29,22 +30,23 @@ ARGV.options do |opt|
29
30
  profile_name = nil
30
31
  credentials_path = nil
31
32
 
32
- opt.on('-p', '--profile PROFILE_NAME') {|v| profile_name = v }
33
- opt.on('' , '--credentials-path PATH') {|v| credentials_path = v }
34
- opt.on('-k', '--access-key ACCESS_KEY') {|v| access_key = v }
35
- opt.on('-s', '--secret-key SECRET_KEY') {|v| secret_key = v }
36
- opt.on('-r', '--region REGION') {|v| region = v }
37
- opt.on('-a', '--apply') { mode = :apply }
38
- opt.on('-f', '--file FILE') {|v| file = v }
39
- opt.on('', '--dry-run') { options[:dry_run] = true }
40
- opt.on('' , '--account-output FILE') {|v| options[:password_manager] = Miam::PasswordManager.new(v, options) }
41
- opt.on('' , '--split') { split = true }
42
- opt.on('-e', '--export') { mode = :export }
43
- opt.on('-o', '--output FILE') {|v| output_file = v }
44
- opt.on('' , '--split') { split = true }
45
- opt.on('' , '--no-color') { options[:color] = false }
46
- opt.on('' , '--no-progress') { options[:no_progress] = true }
47
- opt.on('' , '--debug') { options[:debug] = true }
33
+ opt.on('-p', '--profile PROFILE_NAME') {|v| profile_name = v }
34
+ opt.on('' , '--credentials-path PATH') {|v| credentials_path = v }
35
+ opt.on('-k', '--access-key ACCESS_KEY') {|v| access_key = v }
36
+ opt.on('-s', '--secret-key SECRET_KEY') {|v| secret_key = v }
37
+ opt.on('-r', '--region REGION') {|v| region = v }
38
+ opt.on('-a', '--apply') { mode = :apply }
39
+ opt.on('-f', '--file FILE') {|v| file = v }
40
+ opt.on('' , '--dry-run') { options[:dry_run] = true }
41
+ opt.on('' , '--account-output FILE') {|v| options[:password_manager] = Miam::PasswordManager.new(v, options) }
42
+ opt.on('-e', '--export') { mode = :export }
43
+ opt.on('-o', '--output FILE') {|v| output_file = v }
44
+ opt.on('' , '--split') { split = true }
45
+ opt.on('' , '--split-more') { split = :more }
46
+ opt.on('' , '--export-concurrency N', Integer) {|v| options[:export_concurrency] = v }
47
+ opt.on('' , '--no-color') { options[:color] = false }
48
+ opt.on('' , '--no-progress') { options[:no_progress] = true }
49
+ opt.on('' , '--debug') { options[:debug] = true }
48
50
  opt.parse!
49
51
 
50
52
  aws_opts = {}
@@ -94,10 +96,26 @@ begin
94
96
  output_file = DEFAULT_FILENAME if output_file == '-'
95
97
  requires = []
96
98
 
97
- client.export do |type, dsl|
99
+ client.export(:split_more => (split == :more)) do |args|
100
+ type, dsl = args.values_at(:type, :dsl)
98
101
  next if dsl.strip.empty?
99
- iam_file = File.join(File.dirname(output_file), "#{type}.iam")
100
- requires << iam_file
102
+
103
+ type = type.to_s
104
+ dir = File.dirname(output_file)
105
+
106
+ if split == :more
107
+ name = args[:name]
108
+ dir = File.join(dir, type)
109
+ FileUtils.mkdir_p(dir)
110
+ iam_filename = "#{name}.iam"
111
+ iam_file = File.join(dir, iam_filename)
112
+ requires << File.join(type, iam_filename)
113
+ else
114
+ iam_filename = "#{type}.iam"
115
+ iam_file = File.join(dir, iam_filename)
116
+ requires << iam_filename
117
+ end
118
+
101
119
  logger.info(" write `#{iam_file}`")
102
120
 
103
121
  open(iam_file, 'wb') do |f|
@@ -109,7 +127,7 @@ begin
109
127
 
110
128
  open(output_file, 'wb') do |f|
111
129
  requires.each do |iam_file|
112
- f.puts "require '#{File.basename iam_file}'"
130
+ f.puts "require '#{iam_file}'"
113
131
  end
114
132
  end
115
133
  else
data/lib/miam.rb CHANGED
@@ -3,9 +3,11 @@ require 'json'
3
3
  require 'logger'
4
4
  require 'pp'
5
5
  require 'singleton'
6
+ require 'thread'
6
7
 
7
8
  require 'aws-sdk-core'
8
9
  require 'ruby-progressbar'
10
+ require 'parallel'
9
11
  require 'term/ansicolor'
10
12
 
11
13
  module Miam; end
data/lib/miam/client.rb CHANGED
@@ -9,16 +9,24 @@ class Miam::Client
9
9
  @password_manager = options[:password_manager] || Miam::PasswordManager.new('-', options)
10
10
  end
11
11
 
12
- def export
13
- exported, group_users, instance_profile_roles = Miam::Exporter.export(@iam, @options) do |export_options|
14
- progress(*export_options.values_at(:progress_total, :progress))
15
- end
12
+ def export(export_options = {})
13
+ exported, group_users, instance_profile_roles = Miam::Exporter.export(@iam, @options)
16
14
 
17
15
  if block_given?
18
16
  [:users, :groups, :roles, :instance_profiles].each do |type|
19
17
  splitted = {:users => {}, :groups => {}, :roles => {}, :instance_profiles => {}}
20
- splitted[type] = exported[type]
21
- yield(type, Miam::DSL.convert(splitted, @options).strip)
18
+
19
+ if export_options[:split_more]
20
+ exported[type].each do |name, attrs|
21
+ more_splitted = splitted.dup
22
+ more_splitted[type] = {}
23
+ more_splitted[type][name] = attrs
24
+ yield(:type => type, :name => name, :dsl => Miam::DSL.convert(more_splitted, @options).strip)
25
+ end
26
+ else
27
+ splitted[type] = exported[type]
28
+ yield(:type => type, :dsl => Miam::DSL.convert(splitted, @options).strip)
29
+ end
22
30
  end
23
31
  else
24
32
  Miam::DSL.convert(exported, @options)
@@ -34,10 +42,7 @@ class Miam::Client
34
42
  def walk(file)
35
43
  expected = load_file(file)
36
44
 
37
- actual, group_users, instance_profile_roles = Miam::Exporter.export(@iam, @options) do |export_options|
38
- progress(*export_options.values_at(:progress_total, :progress))
39
- end
40
-
45
+ actual, group_users, instance_profile_roles = Miam::Exporter.export(@iam, @options)
41
46
  updated = walk_groups(expected[:groups], actual[:groups], actual[:users], group_users)
42
47
  updated = walk_users(expected[:users], actual[:users], group_users) || updated
43
48
  updated = walk_instance_profiles(expected[:instance_profiles], actual[:instance_profiles], actual[:roles], instance_profile_roles) || updated
@@ -379,14 +384,4 @@ class Miam::Client
379
384
  raise TypeError, "can't convert #{file} into File"
380
385
  end
381
386
  end
382
-
383
- def progress(total, n)
384
- return if @options[:no_progress]
385
-
386
- unless @progressbar
387
- @progressbar = ProgressBar.create(:title => "Loading", :total => total, :output => $stderr)
388
- end
389
-
390
- @progressbar.progress = n
391
- end
392
387
  end
@@ -131,9 +131,13 @@ instance_profile #{instance_profile_name.inspect}, #{Miam::Utils.unbrace(instanc
131
131
  end
132
132
 
133
133
  def output_policies(policies)
134
- policies.map {|policy_name, policy_document|
135
- output_policy(policy_name, policy_document)
136
- }.join("\n\n ").strip
134
+ if policies.empty?
135
+ "# no policy"
136
+ else
137
+ policies.map {|policy_name, policy_document|
138
+ output_policy(policy_name, policy_document)
139
+ }.join("\n\n ").strip
140
+ end
137
141
  end
138
142
 
139
143
  def output_policy(policy_name, policy_document)
data/lib/miam/exporter.rb CHANGED
@@ -1,14 +1,16 @@
1
1
  class Miam::Exporter
2
- def self.export(iam, options = {}, &block)
3
- self.new(iam, options).export(&block)
2
+ def self.export(iam, options = {})
3
+ self.new(iam, options).export
4
4
  end
5
5
 
6
6
  def initialize(iam, options = {})
7
7
  @iam = iam
8
8
  @options = options
9
+ @mutex = Mutex.new
10
+ @concurrency = options[:export_concurrency] || 16
9
11
  end
10
12
 
11
- def export(&block)
13
+ def export
12
14
  users = list_users
13
15
  groups = list_groups
14
16
  roles = list_roles
@@ -16,16 +18,16 @@ class Miam::Exporter
16
18
  group_users = {}
17
19
  instance_profile_roles = {}
18
20
 
19
- export_options = {
20
- :progress_total => (users.length + groups.length + roles.length + instance_profiles.length),
21
- :progress => 0,
22
- }
21
+ unless @options[:no_progress]
22
+ progress_total = users.length + groups.length + roles.length + instance_profiles.length
23
+ @progressbar = ProgressBar.create(:title => "Loading", :total => progress_total, :output => $stderr)
24
+ end
23
25
 
24
26
  expected = {
25
- :users => export_users(users, group_users, export_options, &block),
26
- :groups => export_groups(groups, export_options, &block),
27
- :roles => export_roles(roles, instance_profile_roles, export_options, &block),
28
- :instance_profiles => export_instance_profiles(instance_profiles, export_options, &block),
27
+ :users => export_users(users, group_users),
28
+ :groups => export_groups(groups),
29
+ :roles => export_roles(roles, instance_profile_roles),
30
+ :instance_profiles => export_instance_profiles(instance_profiles),
29
31
  }
30
32
 
31
33
  [expected, group_users, instance_profile_roles]
@@ -33,33 +35,33 @@ class Miam::Exporter
33
35
 
34
36
  private
35
37
 
36
- def export_users(users, group_users, export_options = {})
38
+ def export_users(users, group_users)
37
39
  result = {}
38
40
 
39
- users.each do |user|
41
+ Parallel.each(users, :in_threads => @concurrency) do |user|
40
42
  user_name = user.user_name
41
-
42
43
  groups = export_user_groups(user_name)
44
+ policies = export_user_policies(user_name)
45
+ login_profile = export_login_profile(user_name)
43
46
 
44
- groups.each do |group_name|
45
- group_users[group_name] ||= []
46
- group_users[group_name] << user_name
47
- end
47
+ @mutex.synchronize do
48
+ groups.each do |group_name|
49
+ group_users[group_name] ||= []
50
+ group_users[group_name] << user_name
51
+ end
48
52
 
49
- result[user_name] = {
50
- :path => user.path,
51
- :groups => groups,
52
- :policies => export_user_policies(user_name),
53
- }
53
+ result[user_name] = {
54
+ :path => user.path,
55
+ :groups => groups,
56
+ :policies => policies,
57
+ }
54
58
 
55
- login_profile = export_login_profile(user_name)
59
+ if login_profile
60
+ result[user_name][:login_profile] = login_profile
61
+ end
56
62
 
57
- if login_profile
58
- result[user_name][:login_profile] = login_profile
63
+ progress
59
64
  end
60
-
61
- export_options[:progress] += 1
62
- yield(export_options) if block_given?
63
65
  end
64
66
 
65
67
  result
@@ -96,19 +98,21 @@ class Miam::Exporter
96
98
  end
97
99
  end
98
100
 
99
- def export_groups(groups, export_options = {})
101
+ def export_groups(groups)
100
102
  result = {}
101
103
 
102
- groups.each do |group|
104
+ Parallel.each(groups, :in_threads => @concurrency) do |group|
103
105
  group_name = group.group_name
106
+ policies = export_group_policies(group_name)
104
107
 
105
- result[group_name] = {
106
- :path => group.path,
107
- :policies => export_group_policies(group_name),
108
- }
108
+ @mutex.synchronize do
109
+ result[group_name] = {
110
+ :path => group.path,
111
+ :policies => policies,
112
+ }
109
113
 
110
- export_options[:progress] += 1
111
- yield(export_options) if block_given?
114
+ progress
115
+ end
112
116
  end
113
117
 
114
118
  result
@@ -128,30 +132,31 @@ class Miam::Exporter
128
132
  result
129
133
  end
130
134
 
131
- def export_roles(roles, instance_profile_roles, export_options = {})
135
+ def export_roles(roles, instance_profile_roles)
132
136
  result = {}
133
137
 
134
- roles.each do |role|
138
+ Parallel.each(roles, :in_threads => @concurrency) do |role|
135
139
  role_name = role.role_name
136
-
137
140
  instance_profiles = export_role_instance_profiles(role_name)
141
+ policies = export_role_policies(role_name)
138
142
 
139
- instance_profiles.each do |instance_profile_name|
140
- instance_profile_roles[instance_profile_name] ||= []
141
- instance_profile_roles[instance_profile_name] << role_name
142
- end
143
+ @mutex.synchronize do
144
+ instance_profiles.each do |instance_profile_name|
145
+ instance_profile_roles[instance_profile_name] ||= []
146
+ instance_profile_roles[instance_profile_name] << role_name
147
+ end
143
148
 
144
- document = CGI.unescape(role.assume_role_policy_document)
149
+ document = CGI.unescape(role.assume_role_policy_document)
145
150
 
146
- result[role_name] = {
147
- :path => role.path,
148
- :assume_role_policy_document => JSON.parse(document),
149
- :instance_profiles => instance_profiles,
150
- :policies => export_role_policies(role_name),
151
- }
151
+ result[role_name] = {
152
+ :path => role.path,
153
+ :assume_role_policy_document => JSON.parse(document),
154
+ :instance_profiles => instance_profiles,
155
+ :policies => policies,
156
+ }
152
157
 
153
- export_options[:progress] += 1
154
- yield(export_options) if block_given?
158
+ progress
159
+ end
155
160
  end
156
161
 
157
162
  result
@@ -179,18 +184,19 @@ class Miam::Exporter
179
184
  result
180
185
  end
181
186
 
182
- def export_instance_profiles(instance_profiles, export_options = {})
187
+ def export_instance_profiles(instance_profiles)
183
188
  result = {}
184
189
 
185
- instance_profiles.each do |instance_profile|
190
+ Parallel.each(instance_profiles, :in_threads => @concurrency) do |instance_profile|
186
191
  instance_profile_name = instance_profile.instance_profile_name
187
192
 
188
- result[instance_profile_name] = {
189
- :path => instance_profile.path,
190
- }
193
+ @mutex.synchronize do
194
+ result[instance_profile_name] = {
195
+ :path => instance_profile.path,
196
+ }
191
197
 
192
- export_options[:progress] += 1
193
- yield(export_options) if block_given?
198
+ progress
199
+ end
194
200
  end
195
201
 
196
202
  result
@@ -227,4 +233,8 @@ class Miam::Exporter
227
233
  resp.instance_profiles.to_a
228
234
  }.flatten
229
235
  end
236
+
237
+ def progress
238
+ @progressbar.increment if @progressbar
239
+ end
230
240
  end
data/lib/miam/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Miam
2
- VERSION = '0.1.1'
2
+ VERSION = '0.1.2'
3
3
  end
data/miam.gemspec CHANGED
@@ -22,6 +22,7 @@ Gem::Specification.new do |spec|
22
22
 
23
23
  spec.add_dependency 'aws-sdk-core', '~> 2.0.3'
24
24
  spec.add_dependency 'ruby-progressbar'
25
+ spec.add_dependency 'parallel'
25
26
  spec.add_dependency 'term-ansicolor'
26
27
  spec.add_development_dependency 'bundler', '~> 1.7'
27
28
  spec.add_development_dependency 'rake', '~> 10.0'
data/spec/spec_helper.rb CHANGED
@@ -76,6 +76,7 @@ def apply(cli = client)
76
76
  end
77
77
 
78
78
  def export(options = {})
79
+ options = {no_progress: true}.merge(options)
79
80
  cli = options.delete(:client) || Aws::IAM::Client.new
80
81
  Miam::Exporter.export(cli, options)[0]
81
82
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: miam
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.1.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Genki Sugawara
@@ -38,6 +38,20 @@ dependencies:
38
38
  - - '>='
39
39
  - !ruby/object:Gem::Version
40
40
  version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: parallel
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - '>='
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - '>='
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
41
55
  - !ruby/object:Gem::Dependency
42
56
  name: term-ansicolor
43
57
  requirement: !ruby/object:Gem::Requirement
@@ -180,7 +194,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
180
194
  version: '0'
181
195
  requirements: []
182
196
  rubyforge_project:
183
- rubygems_version: 2.4.1
197
+ rubygems_version: 2.0.14
184
198
  signing_key:
185
199
  specification_version: 4
186
200
  summary: Miam is a tool to manage IAM.