ncedit 0.3.0 → 0.4.0

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: 10ab95a17f8d56d2402fcaed7806eb747d188ac9
4
- data.tar.gz: cd3418a0471e0182176afab8a84b04dc5cb2fa85
3
+ metadata.gz: 7d5513ec51dfcc0ec6713acd877b0c5778fd1a08
4
+ data.tar.gz: fcdc71622c410f6ce96095a362aabe2e4834b561
5
5
  SHA512:
6
- metadata.gz: 724f3a28bf6580603125026f92b98cc04f110d20485a48c3df1b6e02c8345321b5f2e6cded1599a4777afd069f6333f15cf79ab0608c750ad835f9d5266aaf87
7
- data.tar.gz: 8e1aeee6e7c1fd300954540fca8b2ae3eebe7bc9dc7adf5a06206c8d9501d792e46ed7f66d67e46365b839ae41fe23ac8cde70ae000470e41d36f597bac2af87
6
+ metadata.gz: 53213593a3ce04d985e37e08b06782c43ae6969a595edfd044fcb1c80887cc92e127b99ede09e832fdf759ac16b24b461da22d084591bd995fe054f225530f8d
7
+ data.tar.gz: 2a2877fa3d0eaf0f3c8f81a96a912d3e41855d06eb19da19553dd3a22b3f2637e75d5d4e4c23cdef309daac3392eaca3c4f6a50a2daf9a9d5b1ce62b9663caa7
data/.gitignore CHANGED
@@ -10,3 +10,4 @@
10
10
  # rspec failure tracking
11
11
  .rspec_status
12
12
  *.gem
13
+ /.idea
data/README.md CHANGED
@@ -3,7 +3,7 @@
3
3
 
4
4
  ncedit is a small utility program that lets you edit the Puppet Enterprise Node Classifier rules from the command line.
5
5
 
6
- Why would you want to do this given that we have the excellent [node_manager](https://forge.puppet.com/WhatsARanjit/node_manager) module already on the forge? Well... lots of reasons. First off, using puppet code to drive the Node Classifier means that you have to have the `node_manager` module alread installed, which means that you must already have your [classification rules](https://docs.puppet.com/pe/latest/console_classes_groups_getting_started.html) in to reference the module through [Code Manager](https://docs.puppet.com/pe/latest/code_mgr.html). You could in-theory use Puppet Enterprise's new idempotent installer (just reinstall puppet over the top of itself) to fix this exact issue but then you still have the problem of how to classify your master in order to activate any other new rules (eg node-ttl) you want to use, which are associated with a new [role](https://docs.puppet.com/pe/latest/r_n_p_intro.html) for the Puppet Master.
6
+ Why would you want to do this given that we have the excellent [node_manager](https://forge.puppet.com/WhatsARanjit/node_manager) module already on the forge? Well... lots of reasons. First off, using puppet code to drive the Node Classifier means that you have to have the `node_manager` module already installed, which means that you must already have your [classification rules](https://docs.puppet.com/pe/latest/console_classes_groups_getting_started.html) in to reference the module through [Code Manager](https://docs.puppet.com/pe/latest/code_mgr.html). You could in-theory use Puppet Enterprise's new idempotent installer (just reinstall puppet over the top of itself) to fix this exact issue but then you still have the problem of how to classify your master in order to activate any other new rules (eg node-ttl) you want to use, which are associated with a new [role](https://docs.puppet.com/pe/latest/r_n_p_intro.html) for the Puppet Master.
7
7
 
8
8
  That's where this tool comes in since all you need is root shell on the Puppet Master.
9
9
 
@@ -14,7 +14,7 @@ You can:
14
14
  * Add or remove class parameters
15
15
  * Add or remove rules
16
16
 
17
- ...All from the convenience of the CLI. This also allows this tool to be called from scripts and other systems in order to setup Puppet Enterprise the way you want and with the minimum of effort.
17
+ ...All from the convenience of the CLI. This allows us to be called from scripts and other systems in order to setup Puppet Enterprise the way you want and with the minimum of effort.
18
18
 
19
19
  You have a choice of running `ncedit` for each change you wish to make or collecting all of your edits into either a JSON or YAML file for bulk processing.
20
20
 
@@ -98,38 +98,102 @@ In each case the file needs to be ordered as follows:
98
98
 
99
99
  #### Ensuring changes
100
100
  * `ncedit` is idempotent so you may run the command as often as you like
101
+ * Classes used in rules *must* already exist for classification to succeed, `--smart-update` will do a code redeploy for you if specified.
101
102
 
102
103
  ##### YAML
103
104
  ```shell
104
- ncedit  batch --yaml-file /path/to/batch.yaml
105
+ ncedit batch --smart-update --yaml-file /path/to/batch.yaml
105
106
  ```
106
107
 
107
108
  ##### JSON
108
109
  ```shell
109
- ncedit batch --json-file /path/to/batch.json
110
+ ncedit batch --smart-update --json-file /path/to/batch.json
110
111
  ```
111
112
 
112
113
  ## Making per-item changes
113
114
  If you don't want to go to the hassle of creating a batch file or you have small, dynamic edits you wish to perform, your able to perform individual edits on the command line:
114
115
 
116
+
117
+ ### Practical examples
118
+ One of the main uses of this tool is to configure Puppet Code Manager, so here are the exact commands you need (alternatively make a `batch.yaml` file to do it all in one hit):
119
+
120
+ #### Code Manager R10K checkout URL
121
+ ```shell
122
+ ncedit classes --smart-update --group-name 'PE Master' \
123
+ --class-name puppet_enterprise::profile::master \
124
+ --param-name r10k_remote \
125
+ --param-value https://github.com/puppetlabs/control-repo
126
+ ```
127
+
128
+ #### Code Manager SSH key
129
+ ```shell
130
+ ncedit classes --smart-update --group-name 'PE Master' \
131
+ --class-name puppet_enterprise::profile::master \
132
+ --param-name r10k_ \
133
+ --param-value /etc/puppetlabs/puppetserver/ssh/id_rsa
134
+ ```
135
+
136
+ #### Code Manager proxy server
137
+ ```shell
138
+ ncedit classes --smart-update --group-name 'PE Master' \
139
+ --class-name puppet_enterprise::profile::master \
140
+ --param-name r10k_proxy \
141
+ --param-value http://proxy.megacorp.com:3128
142
+ ```
143
+
144
+
145
+ #### Enable Code Manager
146
+ ```shell
147
+ ncedit classes --smart-update --group-name 'PE Master' \
148
+ --class-name puppet_enterprise::profile::master \
149
+ --param-name code_manager_auto_configure \
150
+ --param-value true
151
+
152
+ ncedit classes --smart-update --group-name 'PE Master' \
153
+ --class-name puppet_enterprise::profile::master \
154
+ --param-name file_sync_enabled \
155
+ --param-value automatic
156
+ ```
157
+
158
+
159
+ #### Add a rule to configure the puppet master with extra classes
160
+ ```shell
161
+ ncedit classes --smart-update --group-name "Puppet Masters" \
162
+ --class-name role::my_puppet_master \
163
+ --rule '["and", ["=",["fact","fqdn"],"'$(facter fqdn)'"]]' \
164
+ --rule-mode replace
165
+ ```
166
+
167
+ * Run puppet and then re-deploy puppet code
168
+ * Create a new group called `Puppet Masters`
169
+ * Make it load the role `role::my_puppet_master`
170
+ * Have it match any host matching the FQDN of the host the command was run from and replace any existing rules for the group
171
+
172
+ #### Refresh the list of classes in the console
173
+ ```shell
174
+ ncedit update_classes
175
+ ```
176
+
115
177
  ### Add a class to group
116
178
  ```shell
117
- ncedit --group-name FOO --class-name BAR
179
+ ncedit classes --group-name FOO --class-name BAR
118
180
  ```
119
181
  * Group will be created if it doesn't exist
120
182
  * Class MUST exist AND puppet must be aware of it (defeat caching) for the request to be accepted
183
+ * Pass `--smart-update` to run puppet and re-deploy classes if desired
121
184
 
122
185
  ### Add a parameter to a class for a group
123
186
  ```shell
124
- ncedit --group-name FOO --class-name BAR --param-name BAZ --param-value BAS
187
+ ncedit classes --group-name FOO --class-name BAR --param-name BAZ --param-value BAS
125
188
  ```
126
189
  * Group will be created if it doesn't exist
127
190
  * Class will be added if it isn't already
128
191
  * Class MUST exist AND puppet must be aware of it (defeat caching) AND the parameter must exist on the class for the request to be accepted
192
+ * Pass `--smart-update` to run puppet and re-deploy classes if desired
129
193
 
130
194
  ### Delete a parameter from a class inside a group
131
195
  ```shell
132
- ncedit --group-name FOO --class-name BAR --param-name BAZ --delete-param
196
+ ncedit classes --group-name FOO --class-name BAR --param-name BAZ --delete-param
133
197
  ```
134
198
  * Group will be created if it doesn't exist
135
199
  * Class will be added if it isn't already
@@ -137,14 +201,14 @@ ncedit --group-name FOO --class-name BAR --param-name BAZ --delete-param
137
201
 
138
202
  ### Delete a class inside a group
139
203
  ```shell
140
- ncedit --group-name FOO --class-name BAR --delete-class
204
+ ncedit classes --group-name FOO --class-name BAR --delete-class
141
205
  ```
142
206
  * Group will be created if it doesn't exist
143
207
  * Ensures the class `BAR` is not defined
144
208
 
145
209
  ### Replace all rules for group
146
210
  ```shell
147
- ncedit --group-name FOO --rule 'JSON_FRAGMENT' --rule-mode replace
211
+ ncedit classes --group-name FOO --rule 'JSON_FRAGMENT' --rule-mode replace
148
212
  ```
149
213
  * Group will be created if it doesn't exist
150
214
  * Completely replaces existing rules for this group
@@ -152,13 +216,22 @@ ncedit --group-name FOO --rule 'JSON_FRAGMENT' --rule-mode replace
152
216
 
153
217
  ### Append a rule to group
154
218
  ```shell
155
- ncedit --group-name FOO --rule 'JSON_FRAGMENT' --rule-mode append
219
+ ncedit classes --group-name FOO --rule 'JSON_FRAGMENT' --rule-mode append
156
220
  ```
157
221
  * Group will be created if it doesn't exist
158
222
  * Appends supplied JSON_FRAGMENT to the group's rules
159
223
  * Example JSON_FRAGMENT: `["and",["=",["fact","osfamily"],"RedHat"]]`
160
224
  * Notice in our example JSON_FRAGMENT that we have *kept* the outer `and` rule. If we supply a conjuctive different to the rule's current value we will change it for the whole rule
161
225
 
226
+ ## Smart updates
227
+ The NC API will only accept rules for classes that currently exist on the system, so its likely that your rules will be rejected if they have not yet been deployed to the master. To make this process as seamless as possible, the `--smart-update` option will perform this task for you as-and-when required. This assumes you have already setup RBAC to grant access to Code Manager, this can be done in a single command using the [pe_rbac gem](https://github.com/declarativesystems/pe_rbac#setting-up-code-manager-on-the-command-line)
228
+
229
+ Smart updates work as follows:
230
+
231
+ * If any of the `r10k_*` or `code_manager_auto_configure` parameters are set, update them immediately
232
+ * Run `puppet agent -t` then `puppet-code deploy --all --wait`
233
+ * Process any remaining directives
234
+
162
235
  ## Troubleshooting
163
236
  * If you cannot install the `ncedit` gem and you are behind a corporate proxy, ensure that you have correctly set your `http_proxy` and `https_proxy` variables on the shell before running `gem install`.
164
237
  * Some corporate proxies will attempt to eavesdrop on all SSL connections which will cause downloads to fail. This can be resolved by installing a CA bundle (be sure you understand the implications of doing so) or domain whitelisting on the proxy itself
@@ -180,4 +253,4 @@ bundle exec rake spec
180
253
 
181
254
  ## Contributing
182
255
 
183
- Bug reports and pull requests are welcome on GitHub at https://github.com/GeoffWilliams/ncedit.
256
+ Bug reports and pull requests are welcome on GitHub at https://github.com/declarativesystems/ncedit.
data/exe/ncedit CHANGED
@@ -6,6 +6,11 @@ require 'ncedit/cmd'
6
6
  # display help if nothing specified
7
7
  ARGV.push('-h') if ARGV.empty?
8
8
 
9
+ # Add the path to the puppet-code command as a fallback. It's last to
10
+ # allow user to override via the real PATH if necessary
11
+ ENV['PATH'] = "#{ENV['PATH']}:/opt/puppetlabs/puppet/bin/:/opt/puppetlabs/client-tools/bin/"
12
+
13
+
9
14
  Escort::App.create do |app|
10
15
  app.version NCEdit::VERSION
11
16
  app.summary "ncedit"
@@ -59,7 +64,11 @@ Escort::App.create do |app|
59
64
  :long => '--rule-mode',
60
65
  :type => :string,
61
66
  )
62
-
67
+ opts.opt(:smart_update,
68
+ 'Smart update',
69
+ :long => '--smart-update',
70
+ :type => :boolean,
71
+ )
63
72
  end
64
73
  command.action do |options, arguments|
65
74
  NCEdit::Cmd::classes(options[:global][:commands][:classes][:options])
@@ -80,12 +89,18 @@ Escort::App.create do |app|
80
89
  :long => '--json-file',
81
90
  :type => :string,
82
91
  )
92
+ opts.opt(:smart_update,
93
+ 'Smart update',
94
+ :long => '--smart-update',
95
+ :type => :boolean,
96
+ )
83
97
  end
84
98
  command.action do |options, arguments|
85
99
  yaml_file = options[:global][:commands][:batch][:options][:yaml_file]
86
100
  json_file = options[:global][:commands][:batch][:options][:json_file]
101
+ smart_update = options[:global][:commands][:batch][:options][:smart_update]
87
102
 
88
- NCEdit::Cmd::batch(yaml_file: yaml_file, json_file: json_file)
103
+ NCEdit::Cmd::batch(yaml_file: yaml_file, json_file: json_file, smart_update: smart_update)
89
104
  end
90
105
  end
91
106
 
@@ -8,6 +8,15 @@ module NCEdit
8
8
  module Cmd
9
9
  DEFAULT_RULE = "or"
10
10
 
11
+ R10K_SETTINGS_CLASS = "puppet_enterprise::profile::master"
12
+ R10K_SETTINGS_PARAMS = [
13
+ "code_manager_auto_configure",
14
+ "r10k_remote",
15
+ "r10k_private_key",
16
+ "r10k_proxy",
17
+ "r10k_postrun",
18
+ ]
19
+
11
20
  def self.init(puppetclassify = nil)
12
21
  if puppetclassify
13
22
  # use passed in puppetclassify if present - allows injection for easy
@@ -213,14 +222,23 @@ module NCEdit
213
222
  # 'badparam'
214
223
  #
215
224
  # 'Puppet Masters':
216
- # 'clases':
225
+ # 'classes':
217
226
  # 'role::puppet::master':
218
227
  # 'append_rules':
219
228
  # - - "="
220
229
  # - "name"
221
230
  # - "vmpump02.puppet.com"
222
- def self.batch(yaml_file: nil, json_file: nil)
231
+ def self.batch(yaml_file: nil, json_file: nil, smart_update: false)
223
232
  data = read_batch_data(yaml_file: yaml_file, json_file: json_file)
233
+
234
+ if smart_update
235
+ needs_reclassify = contains_r10k_settings(data)
236
+ if needs_reclassify
237
+ apply_r10k_settings_now(needs_reclassify)
238
+ end
239
+ puppet_code_deploy
240
+ end
241
+
224
242
  data.each { |group_name, data|
225
243
 
226
244
  Escort::Logger.output.puts "Processing #{group_name}"
@@ -342,7 +360,7 @@ module NCEdit
342
360
  updated
343
361
  end
344
362
 
345
- # Ensure a partualar rule exists in the group["rule"] array
363
+ # Ensure a particular rule exists in the group["rule"] array
346
364
  # This affects only the items in the chain, eg:
347
365
  # [
348
366
  # "or",
@@ -424,7 +442,6 @@ module NCEdit
424
442
  updated
425
443
  end
426
444
 
427
-
428
445
  def self.classes(options)
429
446
  group_name = options[:group_name]
430
447
  class_name = options[:class_name]
@@ -434,6 +451,7 @@ module NCEdit
434
451
  delete_param = options[:delete_param]
435
452
  rule = options[:rule]
436
453
  rule_mode = options[:rule_mode]
454
+ smart_update = options[:smart_update]
437
455
 
438
456
  rule_change = false
439
457
  class_change = false
@@ -460,10 +478,21 @@ module NCEdit
460
478
  class_change |= ensure_param(group, class_name, param_name, nil, delete:true)
461
479
  elsif class_name and param_name and param_value
462
480
  # set a value inside a class
481
+ if smart_update
482
+ if ! is_r10k_param(class_name, param_name)
483
+
484
+ # not an R10K parameter, do an immediate update to make sure any classes
485
+ # we need are in-place
486
+ puppet_code_deploy
487
+ end
488
+ end
463
489
  Escort::Logger.output.puts "Setting parameter #{param_name} to #{param_value} on #{class_name} in #{group_name}"
464
490
  class_change = ensure_class(group, class_name)
465
491
  class_change |= ensure_param(group, class_name, param_name, param_value)
466
492
  elsif class_name
493
+ if smart_update
494
+ puppet_code_deploy
495
+ end
467
496
  Escort::Logger.output.puts "Adding #{class_name} to #{group_name}"
468
497
  class_change = ensure_class(group, class_name)
469
498
  end
@@ -501,5 +530,69 @@ module NCEdit
501
530
  @puppet_https.delete("#{@puppet_url}/puppet-admin-api/v1/environment-cache")
502
531
  @puppet_https.post("#{@rest_api_url}/v1/update-classes")
503
532
  end
533
+
534
+ def self.puppet_code_deploy
535
+ Escort::Logger.output.puts "Running puppet and deploying code..."
536
+
537
+ # if puppet run fails, just deploy the code anyway as the fix needed might
538
+ # be in the update...
539
+ system("puppet agent -t ; puppet-code deploy --all --wait")
540
+ end
541
+
542
+ # Extract the r10k settings ONLY from the passed in data has and update
543
+ # NCAPI with them immediately
544
+ def self.apply_r10k_settings_now(data)
545
+ data.each { |group_name,opts|
546
+ group = nc_group(group_name)
547
+
548
+ if opts.key?("classes")
549
+ Escort::Logger.output.puts "Setting up rules for #{group_name} immediately"
550
+ if ensure_classes_and_params(group, opts["classes"])
551
+ update_group(group_name, classes: group["classes"])
552
+ end
553
+ end
554
+ }
555
+ end
556
+
557
+ # Check if this is an r10k parameter or not
558
+ #
559
+ # @return true if this is to do with R10K otherwise false
560
+ def self.is_r10k_param(class_name, param_name)
561
+ class_name == R10K_SETTINGS_CLASS and R10K_SETTINGS_PARAMS.include?(param_name)
562
+ end
563
+
564
+ # Evaluate whether change instructions contain R10K settings or not
565
+ #
566
+ # @param data Hash of data settings to look at
567
+ # @return false if not found otherwise hash of with just the settings that
568
+ # need to be applied immediately
569
+ def self.contains_r10k_settings(data)
570
+ found = {}
571
+ data.each { |group_name, opts|
572
+ if opts.key?("classes") and opts["classes"].key?(R10K_SETTINGS_CLASS)
573
+ opts["classes"][R10K_SETTINGS_CLASS].each { |param_name,param_value|
574
+ if is_r10k_param(R10K_SETTINGS_CLASS, param_name)
575
+ # make the hash structure we need
576
+ if ! found.key?(group_name)
577
+ found[group_name] = {}
578
+ end
579
+
580
+ if ! found[group_name].key?("classes")
581
+ found[group_name]["classes"] = {}
582
+ end
583
+
584
+ if ! found[group_name]["classes"].key?(R10K_SETTINGS_CLASS)
585
+ found[group_name]["classes"][R10K_SETTINGS_CLASS] = {}
586
+ end
587
+
588
+ found[group_name]["classes"][R10K_SETTINGS_CLASS][param_name] = param_value
589
+ end
590
+ }
591
+ end
592
+ }
593
+
594
+ # Return the found elements if there were any, otherwise simplify to false
595
+ ! found.empty? ? found : false
596
+ end
504
597
  end
505
598
  end
@@ -1,3 +1,3 @@
1
1
  module NCEdit
2
- VERSION = "0.3.0"
2
+ VERSION = "0.4.0"
3
3
  end
@@ -6,12 +6,13 @@ require 'ncedit/version'
6
6
  Gem::Specification.new do |spec|
7
7
  spec.name = "ncedit"
8
8
  spec.version = NCEdit::VERSION
9
- spec.authors = ["Geoff Williams"]
10
- spec.email = ["geoff@geoffwilliams.me.uk"]
9
+ spec.authors = ["Declarative Systems"]
10
+ spec.email = ["sales@declarativesystems.com"]
11
+ spec.license = "Apache-2.0"
11
12
 
12
13
  spec.summary = %q{Edit Puppet Enterprise Node Classifier rules}
13
14
  spec.description = %q{Use the puppet-classify gem to create/edit NC rules}
14
- spec.homepage = "https://github.com/GeoffWilliams/ncedit"
15
+ spec.homepage = "https://github.com/declarativesystems/ncedit"
15
16
 
16
17
 
17
18
  spec.files = `git ls-files -z`.split("\x0").reject do |f|
@@ -26,6 +27,6 @@ Gem::Specification.new do |spec|
26
27
  spec.add_development_dependency "rspec", "~> 3.0"
27
28
 
28
29
  spec.add_runtime_dependency "escort", "0.4.0"
29
- spec.add_runtime_dependency "json", "2.0.3"
30
- spec.add_runtime_dependency "puppetclassify", "0.1.5"
30
+ spec.add_runtime_dependency "json_pure", "2.1.0"
31
+ spec.add_runtime_dependency "puppetclassify", "0.1.7"
31
32
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ncedit
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.0
4
+ version: 0.4.0
5
5
  platform: ruby
6
6
  authors:
7
- - Geoff Williams
7
+ - Declarative Systems
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2017-04-20 00:00:00.000000000 Z
11
+ date: 2017-09-24 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -67,36 +67,36 @@ dependencies:
67
67
  - !ruby/object:Gem::Version
68
68
  version: 0.4.0
69
69
  - !ruby/object:Gem::Dependency
70
- name: json
70
+ name: json_pure
71
71
  requirement: !ruby/object:Gem::Requirement
72
72
  requirements:
73
73
  - - '='
74
74
  - !ruby/object:Gem::Version
75
- version: 2.0.3
75
+ version: 2.1.0
76
76
  type: :runtime
77
77
  prerelease: false
78
78
  version_requirements: !ruby/object:Gem::Requirement
79
79
  requirements:
80
80
  - - '='
81
81
  - !ruby/object:Gem::Version
82
- version: 2.0.3
82
+ version: 2.1.0
83
83
  - !ruby/object:Gem::Dependency
84
84
  name: puppetclassify
85
85
  requirement: !ruby/object:Gem::Requirement
86
86
  requirements:
87
87
  - - '='
88
88
  - !ruby/object:Gem::Version
89
- version: 0.1.5
89
+ version: 0.1.7
90
90
  type: :runtime
91
91
  prerelease: false
92
92
  version_requirements: !ruby/object:Gem::Requirement
93
93
  requirements:
94
94
  - - '='
95
95
  - !ruby/object:Gem::Version
96
- version: 0.1.5
96
+ version: 0.1.7
97
97
  description: Use the puppet-classify gem to create/edit NC rules
98
98
  email:
99
- - geoff@geoffwilliams.me.uk
99
+ - sales@declarativesystems.com
100
100
  executables:
101
101
  - ncedit
102
102
  extensions: []
@@ -118,8 +118,9 @@ files:
118
118
  - lib/ncedit/cmd.rb
119
119
  - lib/ncedit/version.rb
120
120
  - ncedit.gemspec
121
- homepage: https://github.com/GeoffWilliams/ncedit
122
- licenses: []
121
+ homepage: https://github.com/declarativesystems/ncedit
122
+ licenses:
123
+ - Apache-2.0
123
124
  metadata: {}
124
125
  post_install_message:
125
126
  rdoc_options: []