awskeyring 1.8.4 → 1.9.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 +4 -4
- data/README.md +18 -18
- data/Rakefile +3 -3
- data/i18n/en.yml +1 -1
- data/lib/awskeyring/awsapi.rb +1 -1
- data/lib/awskeyring/credential_provider.rb +29 -0
- data/lib/awskeyring/version.rb +1 -1
- data/lib/awskeyring.rb +15 -3
- data/lib/awskeyring_command.rb +46 -20
- data/man/awskeyring.5 +3 -3
- metadata +5 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 6461179e25d74d7a488cc8dd25db6cb3f3965c177f0dd5cdc8fa440f7c0bf1e3
|
4
|
+
data.tar.gz: 30ac24cde26e0b407a89b218e61ecfd5a8f3ed2852d1da3e3339fa0ef82d17c1
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c11cee874dbaa962b252a637ebffb6623fbc0bf05cafaab9e32bbf34b8243dcf0a53e91f1ca6b3f1e4a2e65f3112981cae169334fa89817a866b8efe48a650dd
|
7
|
+
data.tar.gz: e4bbba7de171b98f88a1e3ea9232ab54c09a785712cddf979f232539ec867676bc0e33fe3b763eaf8217feecb3728aad11436326795f30560034ceeb2ac2d769
|
data/README.md
CHANGED
@@ -62,24 +62,24 @@ more details on this config option.
|
|
62
62
|
The CLI is using [Thor](http://whatisthor.com) with help provided interactively.
|
63
63
|
|
64
64
|
Awskeyring commands:
|
65
|
-
awskeyring --version, -v
|
66
|
-
awskeyring add ACCOUNT
|
67
|
-
awskeyring add-role ROLE
|
68
|
-
awskeyring console ACCOUNT
|
69
|
-
awskeyring env ACCOUNT
|
70
|
-
awskeyring exec ACCOUNT command...
|
71
|
-
awskeyring help [COMMAND]
|
72
|
-
awskeyring import ACCOUNT
|
73
|
-
awskeyring initialise
|
74
|
-
awskeyring json ACCOUNT
|
75
|
-
awskeyring list
|
76
|
-
awskeyring list-role
|
77
|
-
awskeyring remove ACCOUNT
|
78
|
-
awskeyring remove-role ROLE
|
79
|
-
awskeyring remove-token ACCOUNT
|
80
|
-
awskeyring rotate ACCOUNT
|
81
|
-
awskeyring token ACCOUNT [ROLE] [
|
82
|
-
awskeyring update ACCOUNT
|
65
|
+
awskeyring --version, -v # Prints the version
|
66
|
+
awskeyring add ACCOUNT # Adds an ACCOUNT to the keyring
|
67
|
+
awskeyring add-role ROLE # Adds a ROLE to the keyring
|
68
|
+
awskeyring console ACCOUNT # Open the AWS Console for the ACCOUNT
|
69
|
+
awskeyring env ACCOUNT # Outputs bourne shell environment exports for an ACCOUNT
|
70
|
+
awskeyring exec ACCOUNT command... # Execute a COMMAND with the environment set for an ACCOUNT
|
71
|
+
awskeyring help [COMMAND] # Describe available commands or one specific command
|
72
|
+
awskeyring import ACCOUNT # Import an ACCOUNT to the keyring from ~/.aws/credentials
|
73
|
+
awskeyring initialise # Initialises a new KEYCHAIN
|
74
|
+
awskeyring json ACCOUNT # Outputs AWS CLI compatible JSON for an ACCOUNT
|
75
|
+
awskeyring list # Prints a list of accounts in the keyring
|
76
|
+
awskeyring list-role # Prints a list of roles in the keyring
|
77
|
+
awskeyring remove ACCOUNT # Removes an ACCOUNT from the keyring
|
78
|
+
awskeyring remove-role ROLE # Removes a ROLE from the keyring
|
79
|
+
awskeyring remove-token ACCOUNT # Removes a token for ACCOUNT from the keyring
|
80
|
+
awskeyring rotate ACCOUNT # Rotate access keys for an ACCOUNT
|
81
|
+
awskeyring token ACCOUNT [ROLE] [CODE] # Create an STS Token from a ROLE or an mfa CODE
|
82
|
+
awskeyring update ACCOUNT # Updates an ACCOUNT in the keyring
|
83
83
|
|
84
84
|
and autocomplete that can be installed with:
|
85
85
|
|
data/Rakefile
CHANGED
@@ -1,7 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require 'bundler/gem_tasks'
|
4
|
-
require 'rspec/core/rake_task'
|
5
4
|
require 'rubocop/rake_task'
|
6
5
|
require 'ronn'
|
7
6
|
require 'github_changelog_generator/task'
|
@@ -49,8 +48,9 @@ end
|
|
49
48
|
desc 'generate manpage'
|
50
49
|
task :ronn do
|
51
50
|
puts 'Running Ronn...'
|
52
|
-
|
53
|
-
|
51
|
+
doc = Ronn::Document.new('man/awskeyring.5.ronn')
|
52
|
+
doc.date = Time.parse(`git show -s --format=%ad --date=short`)
|
53
|
+
File.write('man/awskeyring.5', doc.to_roff)
|
54
54
|
puts "done\n\n"
|
55
55
|
end
|
56
56
|
|
data/i18n/en.yml
CHANGED
@@ -17,7 +17,7 @@ en:
|
|
17
17
|
remove_role_desc: Removes a ROLE from the keyring
|
18
18
|
remove_token_desc: Removes a token for ACCOUNT from the keyring
|
19
19
|
rotate_desc: Rotate access keys for an ACCOUNT
|
20
|
-
token_desc: Create an STS Token from a ROLE or an
|
20
|
+
token_desc: Create an STS Token from a ROLE or an mfa CODE
|
21
21
|
update_desc: Updates an ACCOUNT in the keyring
|
22
22
|
method_option:
|
23
23
|
arn: 'AWS role arn.'
|
data/lib/awskeyring/awsapi.rb
CHANGED
@@ -209,7 +209,7 @@ module Awskeyring
|
|
209
209
|
# Get the signin token param
|
210
210
|
private_class_method def self.token_param(session_json:)
|
211
211
|
get_signin_token_url = AWS_SIGNIN_URL + '?Action=getSigninToken' \
|
212
|
-
|
212
|
+
'&Session=' + CGI.escape(session_json)
|
213
213
|
|
214
214
|
uri = URI(get_signin_token_url)
|
215
215
|
request = Net::HTTP.new(uri.host, uri.port)
|
@@ -0,0 +1,29 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'aws-sdk-core'
|
4
|
+
require 'awskeyring'
|
5
|
+
|
6
|
+
module Awskeyring
|
7
|
+
# Provide a credential provider for use as a library, eg.
|
8
|
+
# require 'awskeyring/credential_provider'
|
9
|
+
# client = Aws::STS::Client.new(
|
10
|
+
# credentials: Awskeyring::CredentialProvider.new("company-acc")
|
11
|
+
# )
|
12
|
+
class CredentialProvider
|
13
|
+
include Aws::CredentialProvider
|
14
|
+
|
15
|
+
attr_accessor :account
|
16
|
+
|
17
|
+
def initialize(account)
|
18
|
+
@account = account
|
19
|
+
end
|
20
|
+
|
21
|
+
# returns a new Aws::Credentials object
|
22
|
+
def credentials
|
23
|
+
cred = Awskeyring.get_valid_creds(account: account)
|
24
|
+
Aws::Credentials.new(cred[:key],
|
25
|
+
cred[:secret],
|
26
|
+
cred[:token])
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
data/lib/awskeyring/version.rb
CHANGED
data/lib/awskeyring.rb
CHANGED
@@ -52,6 +52,7 @@ module Awskeyring # rubocop:disable Metrics/ModuleLength
|
|
52
52
|
prefs = {
|
53
53
|
awskeyring: awskeyring,
|
54
54
|
keyage: DEFAULT_KEY_AGE,
|
55
|
+
browser: DEFAULT_BROWSER_LIST,
|
55
56
|
console: DEFAULT_CONSOLE_LIST
|
56
57
|
}
|
57
58
|
File.new(Awskeyring::PREFS_FILE, 'w').write JSON.dump(prefs)
|
@@ -97,6 +98,17 @@ module Awskeyring # rubocop:disable Metrics/ModuleLength
|
|
97
98
|
all_items.where(account: account).first
|
98
99
|
end
|
99
100
|
|
101
|
+
# return item that matches a prefix if only one.
|
102
|
+
def self.solo_select(list, prefix)
|
103
|
+
return prefix if list.include?(prefix)
|
104
|
+
|
105
|
+
list.select! { |elem| elem.start_with?(prefix) }
|
106
|
+
|
107
|
+
return list.first if list.length == 1
|
108
|
+
|
109
|
+
nil
|
110
|
+
end
|
111
|
+
|
100
112
|
# Add an account item
|
101
113
|
#
|
102
114
|
# @param [String] account The account name to create
|
@@ -317,7 +329,7 @@ module Awskeyring # rubocop:disable Metrics/ModuleLength
|
|
317
329
|
# @param [String] account_name the associated account name.
|
318
330
|
def self.account_exists(account_name)
|
319
331
|
Awskeyring::Validate.account_name(account_name)
|
320
|
-
raise 'Account does not exist' unless
|
332
|
+
raise 'Account does not exist' unless (account_name = solo_select(list_account_names, account_name))
|
321
333
|
|
322
334
|
account_name
|
323
335
|
end
|
@@ -347,7 +359,7 @@ module Awskeyring # rubocop:disable Metrics/ModuleLength
|
|
347
359
|
# @param [String] role_name the associated role name.
|
348
360
|
def self.role_exists(role_name)
|
349
361
|
Awskeyring::Validate.role_name(role_name)
|
350
|
-
raise 'Role does not exist' unless
|
362
|
+
raise 'Role does not exist' unless (role_name = solo_select(list_role_names, role_name))
|
351
363
|
|
352
364
|
role_name
|
353
365
|
end
|
@@ -367,7 +379,7 @@ module Awskeyring # rubocop:disable Metrics/ModuleLength
|
|
367
379
|
# @param [String] token_name the associated account name.
|
368
380
|
def self.token_exists(token_name)
|
369
381
|
Awskeyring::Validate.account_name(token_name)
|
370
|
-
raise 'Token does not exist' unless
|
382
|
+
raise 'Token does not exist' unless (token_name = solo_select(list_token_names, token_name))
|
371
383
|
|
372
384
|
token_name
|
373
385
|
end
|
data/lib/awskeyring_command.rb
CHANGED
@@ -16,7 +16,6 @@ class AwskeyringCommand < Thor # rubocop:disable Metrics/ClassLength
|
|
16
16
|
I18n.backend.load_translations
|
17
17
|
|
18
18
|
map %w[--version -v] => :__version
|
19
|
-
map %w[--help -h] => :help
|
20
19
|
map 'adr' => :add_role
|
21
20
|
map 'assume-role' => :token
|
22
21
|
map 'ls' => :list
|
@@ -125,7 +124,8 @@ class AwskeyringCommand < Thor # rubocop:disable Metrics/ClassLength
|
|
125
124
|
# Print JSON for use with credential_process
|
126
125
|
def json(account)
|
127
126
|
account = ask_check(
|
128
|
-
existing: account, message: I18n.t('message.account'), validator: Awskeyring.method(:account_exists)
|
127
|
+
existing: account, message: I18n.t('message.account'), validator: Awskeyring.method(:account_exists),
|
128
|
+
limited_to: Awskeyring.list_account_names
|
129
129
|
)
|
130
130
|
cred = age_check_and_get(account: account, no_token: options['no-token'])
|
131
131
|
expiry = Time.at(cred[:expiry]) unless cred[:expiry].nil?
|
@@ -177,11 +177,15 @@ class AwskeyringCommand < Thor # rubocop:disable Metrics/ClassLength
|
|
177
177
|
method_option 'no-token', type: :boolean, aliases: '-n', desc: I18n.t('method_option.notoken'), default: false
|
178
178
|
method_option 'no-bundle', type: :boolean, aliases: '-b', desc: I18n.t('method_option.nobundle'), default: false
|
179
179
|
# execute an external command with env set
|
180
|
-
def exec(account, *command)
|
180
|
+
def exec(account, *command) # rubocop:disable Metrics/MethodLength, Metrics/AbcSize
|
181
181
|
if command.empty?
|
182
182
|
warn I18n.t('message.exec')
|
183
183
|
exit 1
|
184
184
|
end
|
185
|
+
account = ask_check(
|
186
|
+
existing: account, message: I18n.t('message.account'), validator: Awskeyring.method(:account_exists),
|
187
|
+
limited_to: Awskeyring.list_account_names
|
188
|
+
)
|
185
189
|
cred = age_check_and_get(account: account, no_token: options['no-token'])
|
186
190
|
env_vars = Awskeyring::Awsapi.get_env_array(cred)
|
187
191
|
unbundle if options['no-bundle']
|
@@ -335,7 +339,7 @@ class AwskeyringCommand < Thor # rubocop:disable Metrics/ClassLength
|
|
335
339
|
puts I18n.t('message.upaccount', account: account)
|
336
340
|
end
|
337
341
|
|
338
|
-
desc 'token ACCOUNT [ROLE] [
|
342
|
+
desc 'token ACCOUNT [ROLE] [CODE]', I18n.t('token_desc')
|
339
343
|
method_option :code, type: :string, aliases: '-c', desc: I18n.t('method_option.code')
|
340
344
|
method_option :duration, type: :string, aliases: '-d', desc: I18n.t('method_option.duration')
|
341
345
|
# generate a sessiopn token
|
@@ -430,7 +434,8 @@ class AwskeyringCommand < Thor # rubocop:disable Metrics/ClassLength
|
|
430
434
|
desc "#{File.basename($PROGRAM_NAME)} CURR PREV", I18n.t('awskeyring_desc'), hide: true
|
431
435
|
map File.basename($PROGRAM_NAME) => :autocomplete
|
432
436
|
# autocomplete
|
433
|
-
def autocomplete(curr, prev)
|
437
|
+
def autocomplete(curr, prev = nil)
|
438
|
+
curr, prev = fix_args(curr, prev)
|
434
439
|
comp_line = ENV['COMP_LINE']
|
435
440
|
comp_point_str = ENV['COMP_POINT']
|
436
441
|
unless comp_line && comp_point_str
|
@@ -448,16 +453,16 @@ class AwskeyringCommand < Thor # rubocop:disable Metrics/ClassLength
|
|
448
453
|
|
449
454
|
private
|
450
455
|
|
451
|
-
|
452
|
-
|
453
|
-
|
454
|
-
|
455
|
-
|
456
|
-
|
457
|
-
|
458
|
-
cred
|
456
|
+
# when a double dash is parsed it is dropped from the args but we need it
|
457
|
+
def fix_args(curr, prev)
|
458
|
+
if prev.nil?
|
459
|
+
[ARGV[1], ARGV[2]]
|
460
|
+
else
|
461
|
+
[curr, prev]
|
462
|
+
end
|
459
463
|
end
|
460
464
|
|
465
|
+
# determine the type of completion needed
|
461
466
|
def comp_type(comp_lines:, prev:)
|
462
467
|
sub_cmd = sub_command(comp_lines)
|
463
468
|
comp_idx = comp_lines.rindex(prev)
|
@@ -475,8 +480,10 @@ class AwskeyringCommand < Thor # rubocop:disable Metrics/ClassLength
|
|
475
480
|
[comp_type, sub_cmd]
|
476
481
|
end
|
477
482
|
|
483
|
+
# check params for named params or fall back to flags
|
478
484
|
def param_type(comp_idx, sub_cmd)
|
479
|
-
|
485
|
+
types = %i[opt req]
|
486
|
+
param_list = method(sub_cmd).parameters.select { |elem| types.include? elem[0] }
|
480
487
|
if comp_idx.zero?
|
481
488
|
:command
|
482
489
|
elsif comp_idx > param_list.length
|
@@ -486,18 +493,18 @@ class AwskeyringCommand < Thor # rubocop:disable Metrics/ClassLength
|
|
486
493
|
end
|
487
494
|
end
|
488
495
|
|
496
|
+
# catch the command from prefixes and aliases
|
489
497
|
def sub_command(comp_lines)
|
490
|
-
return '' if comp_lines.
|
498
|
+
return '' if comp_lines.length < 2
|
491
499
|
|
492
|
-
sub_cmd = comp_lines[1]
|
500
|
+
sub_cmd = comp_lines[1]
|
493
501
|
|
494
|
-
|
502
|
+
return self.class.map[sub_cmd].to_s if self.class.map.key? sub_cmd
|
495
503
|
|
496
|
-
|
497
|
-
|
498
|
-
self.class.map[sub_cmd].to_s
|
504
|
+
(Awskeyring.solo_select(list_commands, sub_cmd) || '').tr('-', '_')
|
499
505
|
end
|
500
506
|
|
507
|
+
# given a type return the right list for completions
|
501
508
|
def fetch_auto_resp(comp_type, sub_cmd)
|
502
509
|
case comp_type
|
503
510
|
when :command
|
@@ -517,11 +524,13 @@ class AwskeyringCommand < Thor # rubocop:disable Metrics/ClassLength
|
|
517
524
|
end
|
518
525
|
end
|
519
526
|
|
527
|
+
# list command names
|
520
528
|
def list_commands
|
521
529
|
commands = self.class.all_commands.keys.map { |elem| elem.tr('_', '-') }
|
522
530
|
commands.reject! { |elem| %w[autocomplete default].include?(elem) }
|
523
531
|
end
|
524
532
|
|
533
|
+
# list flags for a command
|
525
534
|
def list_arguments(command:)
|
526
535
|
options = self.class.all_commands[command].options.values
|
527
536
|
exit 1 if options.empty?
|
@@ -530,18 +539,32 @@ class AwskeyringCommand < Thor # rubocop:disable Metrics/ClassLength
|
|
530
539
|
options.map(&:switch_name)
|
531
540
|
end
|
532
541
|
|
542
|
+
# add warning about old keys
|
543
|
+
def age_check_and_get(account:, no_token:)
|
544
|
+
cred = Awskeyring.get_valid_creds(account: account, no_token: no_token)
|
545
|
+
|
546
|
+
maxage = Awskeyring.key_age
|
547
|
+
age = (Time.new - cred[:updated]).div Awskeyring::Awsapi::ONE_DAY
|
548
|
+
warn I18n.t('message.age_check', account: account, age: age) unless age < maxage
|
549
|
+
|
550
|
+
cred
|
551
|
+
end
|
552
|
+
|
553
|
+
# print exports from map
|
533
554
|
def put_env_string(cred)
|
534
555
|
env_var = Awskeyring::Awsapi.get_env_array(cred)
|
535
556
|
env_var.each { |var, value| puts "export #{var}=\"#{value}\"" }
|
536
557
|
Awskeyring::Awsapi::AWS_ENV_VARS.each { |key| puts "unset #{key}" unless env_var.key?(key) }
|
537
558
|
end
|
538
559
|
|
560
|
+
# select duration for sts token types
|
539
561
|
def default_duration(duration, role, code)
|
540
562
|
duration ||= Awskeyring::Awsapi::ONE_HOUR.to_s if role
|
541
563
|
duration ||= Awskeyring::Awsapi::TWELVE_HOUR.to_s if code
|
542
564
|
duration || Awskeyring::Awsapi::ONE_HOUR.to_s
|
543
565
|
end
|
544
566
|
|
567
|
+
# ask and validate input values.
|
545
568
|
def ask_check(existing:, message:, flags: nil, validator: nil, limited_to: nil) # rubocop:disable Metrics/MethodLength
|
546
569
|
retries ||= 3
|
547
570
|
begin
|
@@ -562,10 +585,12 @@ class AwskeyringCommand < Thor # rubocop:disable Metrics/ClassLength
|
|
562
585
|
value
|
563
586
|
end
|
564
587
|
|
588
|
+
# ask for somthinng if its missing.
|
565
589
|
def ask_missing(existing:, message:, secure: false, optional: false, limited_to: nil)
|
566
590
|
existing || ask(message: message, secure: secure, optional: optional, limited_to: limited_to).strip
|
567
591
|
end
|
568
592
|
|
593
|
+
# ask in different ways
|
569
594
|
def ask(message:, secure: false, optional: false, limited_to: nil)
|
570
595
|
if secure
|
571
596
|
Awskeyring::Input.read_secret("#{message.rjust(20)}: ")
|
@@ -578,6 +603,7 @@ class AwskeyringCommand < Thor # rubocop:disable Metrics/ClassLength
|
|
578
603
|
end
|
579
604
|
end
|
580
605
|
|
606
|
+
# undo Bundler env vars
|
581
607
|
def unbundle
|
582
608
|
to_delete = ENV.keys.select { |elem| elem.start_with?('BUNDLER_ORIG_') }
|
583
609
|
bundled_env = to_delete.map { |elem| elem[('BUNDLER_ORIG_'.length)..] }
|
data/man/awskeyring.5
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
.\" generated with Ronn/v0.7.3
|
2
2
|
.\" http://github.com/rtomayko/ronn/tree/0.7.3
|
3
3
|
.
|
4
|
-
.TH "AWSKEYRING" "5" "
|
4
|
+
.TH "AWSKEYRING" "5" "September 2021" "" ""
|
5
5
|
.
|
6
6
|
.SH "NAME"
|
7
7
|
\fBAwskeyring\fR \- is a small tool to manage AWS account keys in the macOS Keychain
|
@@ -189,10 +189,10 @@ rotate ACCOUNT:
|
|
189
189
|
Rotate access keys for an ACCOUNT
|
190
190
|
.
|
191
191
|
.TP
|
192
|
-
token ACCOUNT [ROLE] [
|
192
|
+
token ACCOUNT [ROLE] [CODE]:
|
193
193
|
.
|
194
194
|
.IP
|
195
|
-
Create an STS Token from a ROLE or an
|
195
|
+
Create an STS Token from a ROLE or an mfa CODE
|
196
196
|
.
|
197
197
|
.br
|
198
198
|
.
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: awskeyring
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.9.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Tristan Morgan
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2021-
|
11
|
+
date: 2021-09-13 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: aws-sdk-iam
|
@@ -82,6 +82,7 @@ files:
|
|
82
82
|
- i18n/en.yml
|
83
83
|
- lib/awskeyring.rb
|
84
84
|
- lib/awskeyring/awsapi.rb
|
85
|
+
- lib/awskeyring/credential_provider.rb
|
85
86
|
- lib/awskeyring/input.rb
|
86
87
|
- lib/awskeyring/validate.rb
|
87
88
|
- lib/awskeyring/version.rb
|
@@ -93,8 +94,8 @@ licenses:
|
|
93
94
|
metadata:
|
94
95
|
bug_tracker_uri: https://github.com/servian/awskeyring/issues
|
95
96
|
changelog_uri: https://github.com/servian/awskeyring/blob/main/CHANGELOG.md
|
96
|
-
documentation_uri: https://rubydoc.info/gems/awskeyring/1.
|
97
|
-
source_code_uri: https://github.com/servian/awskeyring/tree/v1.
|
97
|
+
documentation_uri: https://rubydoc.info/gems/awskeyring/1.9.2
|
98
|
+
source_code_uri: https://github.com/servian/awskeyring/tree/v1.9.2
|
98
99
|
wiki_uri: https://github.com/servian/awskeyring/wiki
|
99
100
|
post_install_message:
|
100
101
|
rdoc_options: []
|