miam 0.1.1 → 0.1.2

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