puppet-magnum 3.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (46) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +20 -0
  3. data/.rspec +3 -0
  4. data/.ruby-version +1 -0
  5. data/.travis.yml +1 -0
  6. data/Gemfile +2 -0
  7. data/Gemfile.lock +73 -0
  8. data/LICENSE +13 -0
  9. data/README.md +247 -0
  10. data/Rakefile +20 -0
  11. data/VERSION +1 -0
  12. data/bin/puppet-magnum +6 -0
  13. data/generator_files/CHANGELOG.md.erb +0 -0
  14. data/generator_files/README.md.erb +11 -0
  15. data/generator_files/git/gitignore.erb +40 -0
  16. data/generator_files/licenses/apachev2.erb +13 -0
  17. data/generator_files/licenses/mit.erb +20 -0
  18. data/generator_files/licenses/reserved.erb +2 -0
  19. data/generator_files/puppet-magnum.init.erb +1 -0
  20. data/generator_files/puppet/init.pp.erb +47 -0
  21. data/generator_files/puppet/metadata.json.erb +26 -0
  22. data/generator_files/puppet/params.pp.erb +16 -0
  23. data/generator_files/spec/fixtures.yml.erb +9 -0
  24. data/generator_files/spec/rspec.erb +2 -0
  25. data/generator_files/spec/rspec/init_spec.rb.erb +6 -0
  26. data/generator_files/spec/rspec/spec_helper.rb.erb +10 -0
  27. data/generator_files/spec/serverspec/init_spec.rb.erb +5 -0
  28. data/generator_files/util/Gemfile.erb +10 -0
  29. data/generator_files/util/Rakefile.erb +35 -0
  30. data/generator_files/vagrant/Vagrantfile.erb +33 -0
  31. data/generator_files/vagrant/environment/environment.conf.erb +18 -0
  32. data/generator_files/vagrant/environment/manifests/init.pp.erb +1 -0
  33. data/generator_files/vagrant/init.sh.erb +23 -0
  34. data/lib/puppet-magnum.rb +13 -0
  35. data/lib/puppet-magnum/cli.rb +16 -0
  36. data/lib/puppet-magnum/cli/module.rb +32 -0
  37. data/lib/puppet-magnum/generators/base_generator.rb +23 -0
  38. data/lib/puppet-magnum/generators/create_generator.rb +188 -0
  39. data/lib/puppet-magnum/version.rb +3 -0
  40. data/puppet-magnum.gemspec +40 -0
  41. data/spec/lib/puppet-magnum/cli_spec.rb +18 -0
  42. data/spec/lib/puppet-magnum/generators/base_generator_spec.rb +11 -0
  43. data/spec/lib/puppet-magnum/generators/create_generator_spec.rb +4 -0
  44. data/spec/lib/puppet_magnum_spec.rb +20 -0
  45. data/spec/spec_helper.rb +35 -0
  46. metadata +264 -0
@@ -0,0 +1,13 @@
1
+ Copyright (c) <%= copyright_year %> <%= copyright_holder %>
2
+
3
+ Licensed under the Apache License, Version 2.0 (the "License");
4
+ you may not use this file except in compliance with the License.
5
+ You may obtain a copy of the License at
6
+
7
+ http://www.apache.org/licenses/LICENSE-2.0
8
+
9
+ Unless required by applicable law or agreed to in writing, software
10
+ distributed under the License is distributed on an "AS IS" BASIS,
11
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ See the License for the specific language governing permissions and
13
+ limitations under the License.
@@ -0,0 +1,20 @@
1
+ Copyright (c) <%= copyright_year %> <%= copyright_holder %>
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,2 @@
1
+ Copyright (c) <%= copyright_year %> <%= copyright_holder %>
2
+ All Rights Reserved - Do Not Redistribute
@@ -0,0 +1 @@
1
+ <%= puppet_magnum_init_timestamp %>
@@ -0,0 +1,47 @@
1
+ # Class: <%= module_name %>
2
+ # ===========================
3
+ #
4
+ # Full description of class <%= module_name %> here.
5
+ #
6
+ # Parameters
7
+ # ----------
8
+ #
9
+ # Document parameters here.
10
+ #
11
+ # * `sample parameter`
12
+ # Explanation of what this parameter affects and what it defaults to.
13
+ # e.g. "Specify one or more upstream ntp servers as an array."
14
+ #
15
+ # Variables
16
+ # ---------
17
+ #
18
+ # Here you should define a list of variables that this module would require.
19
+ #
20
+ # * `sample variable`
21
+ # Explanation of how this variable affects the function of this class and if
22
+ # it has a default. e.g. "The parameter enc_ntp_servers must be set by the
23
+ # External Node Classifier as a comma separated list of hostnames." (Note,
24
+ # global variables should be avoided in favor of class parameters as
25
+ # of Puppet 2.6.)
26
+ #
27
+ # Examples
28
+ # --------
29
+ #
30
+ # @example
31
+ # class { '<%= module_name %>':
32
+ # servers => [ 'pool.ntp.org', 'ntp.local.company.com' ],
33
+ # }
34
+ #
35
+ # Authors
36
+ # -------
37
+ #
38
+ # Author Name: <%= maintainer_email %>
39
+ #
40
+ # Copyright
41
+ # ---------
42
+ #
43
+ # Copyright (C) <%= copyright_year %> <%= copyright_holder %>
44
+ #
45
+ class <%= module_name %> {
46
+
47
+ }
@@ -0,0 +1,26 @@
1
+ {
2
+ "name": "<%= module_name %>",
3
+ "summary": "<%= module_name %>",
4
+ "tags": ["<%= module_name %>"],
5
+ "author": "<%= maintainer_email %>",
6
+ "license": "<%= license_name %>",
7
+ "dependencies": [
8
+ {
9
+ "name": "puppetlabs/stdlib",
10
+ "version_requirement": ">= 3.2.0"
11
+ }
12
+ ],
13
+ "operatingsystem_support": [
14
+ {
15
+ "operatingsystem": "Ubuntu",
16
+ "operatingsystemrelease": [
17
+ "14.04"
18
+ ]
19
+ }
20
+ ],
21
+ "source": "https://example.com",
22
+ "project_page": "https://example.com",
23
+ "issues_url": "https://example.com",
24
+ "data_provider": null,
25
+ "version": "1.0.0"
26
+ }
@@ -0,0 +1,16 @@
1
+ # Class: <%= module_name %>::params
2
+ # ===========================
3
+ #
4
+ # Authors
5
+ # -------
6
+ #
7
+ # Author Name: <%= maintainer_email %>
8
+ #
9
+ # Copyright
10
+ # ---------
11
+ #
12
+ # Copyright (C) <%= copyright_year %> <%= copyright_holder %>
13
+ #
14
+ class <%= module_name %>::params {
15
+
16
+ }
@@ -0,0 +1,9 @@
1
+ # For puppetlabs_spec_helper documentation - see https://github.com/puppetlabs/puppetlabs_spec_helper
2
+
3
+ fixtures:
4
+ repositories:
5
+ stdlib: 'git://github.com/puppetlabs/puppetlabs-stdlib'
6
+ symlinks:
7
+ <%= module_name %>/files: '../../../../files'
8
+ <%= module_name %>/manifests: '../../../../manifests'
9
+ <%= module_name %>/templates: '../../../../templates'
@@ -0,0 +1,2 @@
1
+ --color
2
+ --format documentation
@@ -0,0 +1,6 @@
1
+ # for rspec-puppet documentation - see http://rspec-puppet.com/tutorial/
2
+ require_relative '../spec_helper'
3
+
4
+ describe '<%= module_name %>' do
5
+ it 'should do something'
6
+ end
@@ -0,0 +1,10 @@
1
+ require 'rspec-puppet'
2
+ require 'puppetlabs_spec_helper/module_spec_helper'
3
+ require 'puppetlabs_spec_helper/puppetlabs_spec_helper'
4
+
5
+ fixture_path = File.expand_path(File.join(__FILE__, '..', 'fixtures'))
6
+
7
+ RSpec.configure do |c|
8
+ c.module_path = File.join(fixture_path, 'modules')
9
+ c.manifest_dir = File.join(fixture_path, 'manifests')
10
+ end
@@ -0,0 +1,5 @@
1
+ # For serverspec documentation - see http://serverspec.org/tutorial.html
2
+
3
+ describe '<%= module_name %>' do
4
+ it 'should do something'
5
+ end
@@ -0,0 +1,10 @@
1
+ source 'http://rubygems.org'
2
+
3
+ gem 'rake'
4
+ gem 'colorize'
5
+
6
+ gem 'puppet', '~> 4.4.1'
7
+ gem 'rspec', '~> 3.1.0'
8
+ gem 'puppet-lint', '~> 1.1.0'
9
+ gem 'rspec-puppet', '~> 2.4.0'
10
+ gem 'puppetlabs_spec_helper', '~> 1.1.1'
@@ -0,0 +1,35 @@
1
+ require 'rake'
2
+ require 'colorize'
3
+ require 'rspec/core/rake_task'
4
+ require 'puppet-lint/tasks/puppet-lint'
5
+ require 'puppetlabs_spec_helper/rake_tasks'
6
+
7
+ desc 'Run unit tests'
8
+ task :unit do
9
+ Rake::Task[:spec_prep].invoke
10
+ Rake::Task[:spec_standalone].invoke
11
+ end
12
+ task :spec => []; Rake::Task[:spec].clear
13
+ task :spec => :unit
14
+
15
+ desc 'Run syntax, lint and unit tests'
16
+ task :test do
17
+ Rake::Task[:syntax].invoke
18
+ Rake::Task[:lint].invoke
19
+ Rake::Task[:unit].invoke
20
+ end
21
+
22
+ # puppet-lint options
23
+ Rake::Task[:lint].clear
24
+ PuppetLint::RakeTask.new :lint do |config|
25
+ config.ignore_paths = ['spec/**/*.pp']
26
+ config.log_format = '%{path}:%{linenumber}:%{check}:%{KIND}:%{message}'
27
+ config.disable_checks = [ "class_inherits_from_params_class", "disable_autoloader_layout", "80chars" ]
28
+ config.fail_on_warnings = false
29
+ end
30
+
31
+ # remove undesired rake tasks
32
+ task :build => []; Rake::Task[:build].clear
33
+ task :clean => []; Rake::Task[:clean].clear
34
+ task :default => []; Rake::Task[:default].clear
35
+ task :default => :test
@@ -0,0 +1,33 @@
1
+ # -*- mode: ruby -*-
2
+ # vi: set ft=ruby :
3
+
4
+ VAGRANTFILE_API_VERSION = '2'
5
+
6
+ Vagrant.require_version '>= 1.8.0'
7
+ Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
8
+
9
+ # Using Puppet Labs official Vagrant boxes, from: https://atlas.hashicorp.com/puppetlabs
10
+ config.vm.box = 'puppetlabs/ubuntu-14.04-64-puppet'
11
+
12
+ config.vm.provider 'virtualbox' do |vbox|
13
+ vbox.memory = 1024
14
+ # vbox.cpus = 2
15
+ end
16
+
17
+ config.vm.provision :shell, :path => '.vagrant_puppet/init.sh'
18
+
19
+ config.vm.provision :puppet do |puppet|
20
+ puppet.environment_path = '.vagrant_puppet/environments'
21
+ puppet.environment = 'vagrant'
22
+ puppet.options = '--verbose'
23
+ end
24
+
25
+ config.vm.provision :serverspec do |spec|
26
+ spec.pattern = 'serverspec/*_spec.rb'
27
+ end
28
+
29
+ end
30
+
31
+ unless Vagrant.has_plugin?('vagrant-serverspec')
32
+ raise 'vagrant-serverspec is not installed!'
33
+ end
@@ -0,0 +1,18 @@
1
+ # Each environment can have an environment.conf file. Its settings will only
2
+ # affect its own environment. See docs for more info:
3
+ # https://docs.puppetlabs.com/puppet/latest/reference/config_file_environment.html
4
+
5
+ # Any unspecified settings use default values; some of those defaults are based
6
+ # on puppet.conf settings.
7
+
8
+ # If these settings include relative file paths, they'll be resolved relative to
9
+ # this environment's directory.
10
+
11
+ # Allowed settings and default values:
12
+
13
+ # modulepath = ./modules:$basemodulepath
14
+ # manifest = (default_manifest from puppet.conf, which defaults to ./manifests)
15
+ # config_version = (no script; Puppet will use the time the catalog was compiled)
16
+ # environment_timeout = (environment_timeout from puppet.conf, which defaults to 0)
17
+ # Note: unless you have a specific reason, we recommend only setting
18
+ # environment_timeout in puppet.conf.
@@ -0,0 +1 @@
1
+ include <%= module_name %>
@@ -0,0 +1,23 @@
1
+ #!/bin/bash
2
+
3
+ STAGE='/tmp/magnum-vagrant-stage'
4
+
5
+ FIXTURES_DIR='/vagrant/spec/fixtures/modules'
6
+ VAGRANT_PUPPET_ENV_DIR='/tmp/vagrant-puppet/environments/vagrant'
7
+
8
+ if [ ! -e $STAGE ]; then
9
+
10
+ echo "Initial provision, running the magnum-vagrant shell provisioner script..."
11
+
12
+ apt-get update
13
+
14
+ mkdir -p $VAGRANT_PUPPET_ENV_DIR
15
+ ln -sfn $FIXTURES_DIR $VAGRANT_PUPPET_ENV_DIR/modules
16
+
17
+ touch $STAGE
18
+
19
+ else
20
+ echo "Not initial provision, skipping the magnum-vagrant shell provisioner script..."
21
+ fi
22
+
23
+ exit 0
@@ -0,0 +1,13 @@
1
+ require 'thor'
2
+ require 'pathname'
3
+
4
+ module PuppetMagnum
5
+ autoload :BaseGenerator, 'puppet-magnum/generators/base_generator'
6
+ autoload :CreateGenerator, 'puppet-magnum/generators/create_generator'
7
+ autoload :Cli, 'puppet-magnum/cli'
8
+ autoload :Module, 'puppet-magnum/cli/module'
9
+
10
+ def self.root
11
+ @root ||= Pathname.new(File.expand_path('../', File.dirname(__FILE__)))
12
+ end
13
+ end
@@ -0,0 +1,16 @@
1
+ require 'thor'
2
+ require_relative './version'
3
+
4
+ module PuppetMagnum
5
+ class Cli < Thor
6
+
7
+ desc 'module', 'Module related tasks. Type \'puppet-magnum module\' for more help.'
8
+ subcommand 'module', Module
9
+
10
+ desc 'version', 'Display version information.'
11
+ def version
12
+ puts "puppet-magnum (#{PuppetMagnum::VERSION.chomp})"
13
+ end
14
+
15
+ end
16
+ end
@@ -0,0 +1,32 @@
1
+ require 'thor'
2
+ require 'yaml'
3
+
4
+ module PuppetMagnum
5
+ class Module < Thor
6
+
7
+ desc 'create [MODULE_NAME]', 'Creates a new Puppet module.'
8
+ def create(module_name)
9
+ PuppetMagnum::CreateGenerator.new([File.join(Dir.pwd, module_name), module_name], options).invoke_all
10
+ end
11
+
12
+ desc 'init [MODULE_NAME]', 'Initializes an existing Puppet module.'
13
+ def init(module_name)
14
+ PuppetMagnum::CreateGenerator.new([File.join(Dir.pwd, module_name), module_name], options).invoke_all
15
+ end
16
+
17
+ def self.banner(task, namespace = false, subcommand = true)
18
+ "#{basename} #{task.formatted_usage(self, namespace, subcommand).split(':').join(' ')}"
19
+ end
20
+
21
+ private
22
+ def options
23
+ original_options = super
24
+
25
+ rcfile = File.expand_path('~/.magnumrc')
26
+ return original_options unless File.exists?(rcfile)
27
+
28
+ defaults = ::YAML::load_file(rcfile) || {}
29
+ Thor::CoreExt::HashWithIndifferentAccess.new(defaults.merge(original_options))
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,23 @@
1
+ require 'pathname'
2
+
3
+ module PuppetMagnum
4
+ class BaseGenerator < Thor::Group
5
+ include Thor::Actions
6
+ include Thor::Shell
7
+
8
+ argument :path,
9
+ type: :string,
10
+ required: true
11
+
12
+ def self.source_root
13
+ PuppetMagnum.root.join('generator_files')
14
+ end
15
+
16
+ private
17
+
18
+ def target
19
+ @target ||= Pathname.new(File.expand_path(path))
20
+ end
21
+
22
+ end
23
+ end
@@ -0,0 +1,188 @@
1
+ module PuppetMagnum
2
+ class CreateGenerator < BaseGenerator
3
+
4
+ argument :module_name,
5
+ type: :string,
6
+ required: true
7
+
8
+ class_option :license,
9
+ type: :string,
10
+ default: 'reserved'
11
+
12
+ class_option :maintainer,
13
+ type: :string,
14
+ default: 'Example, Inc.'
15
+
16
+ class_option :maintainer_email,
17
+ type: :string,
18
+ default: 'puppet@example.com'
19
+
20
+ class_option :copyright_holder,
21
+ type: :string
22
+
23
+ def write_emptydirs
24
+ empty_directory target.join('manifests')
25
+ empty_directory target.join('templates')
26
+ empty_directory target.join('files')
27
+ empty_directory target.join('spec')
28
+ empty_directory target.join('serverspec')
29
+ empty_directory target.join('.vagrant_puppet')
30
+ end
31
+
32
+ def write_readme
33
+ template 'README.md.erb', target.join('README.md')
34
+ end
35
+
36
+ def write_changelog
37
+ template 'CHANGELOG.md.erb', target.join('CHANGELOG.md')
38
+ end
39
+
40
+ def write_license
41
+ template license_file, target.join('LICENSE')
42
+ end
43
+
44
+ def write_metadata_json
45
+ template 'puppet/metadata.json.erb', target.join('metadata.json')
46
+ end
47
+
48
+ def write_manifests_templates_files
49
+ template 'puppet/init.pp.erb', target.join('manifests/init.pp')
50
+ template 'puppet/params.pp.erb', target.join('manifests/params.pp')
51
+ end
52
+
53
+ def write_spec_setup
54
+ spec_dirs = [ 'classes', 'defines', 'functions', 'hosts', 'unit' ]
55
+ spec_dirs.each do |dir|
56
+ empty_directory target.join("spec/#{dir}")
57
+ end
58
+
59
+ empty_directory target.join('spec/fixtures/manifests')
60
+ create_file target.join('spec/fixtures/manifests/site.pp')
61
+
62
+ empty_directory target.join("spec/fixtures/modules/#{module_name}")
63
+ spec_dirs = ['manifests', 'templates', 'files']
64
+ spec_dirs.each { |spec_dir|
65
+ remove_file target.join("spec/fixtures/modules/#{module_name}/#{spec_dir}")
66
+ create_link target.join("spec/fixtures/modules/#{module_name}/#{spec_dir}"), "../../../../#{spec_dir}"
67
+ }
68
+
69
+ template 'spec/rspec/spec_helper.rb.erb', target.join('spec/spec_helper.rb')
70
+ template 'spec/rspec/init_spec.rb.erb', target.join("spec/classes/#{module_name}_spec.rb")
71
+
72
+ template 'spec/rspec.erb', target.join('.rspec')
73
+ end
74
+
75
+ def write_serverspec_setup
76
+ template 'spec/serverspec/init_spec.rb.erb', target.join("serverspec/#{module_name}_spec.rb")
77
+ end
78
+
79
+ def write_fixtures
80
+ template 'spec/fixtures.yml.erb', target.join('.fixtures.yml')
81
+ end
82
+
83
+ def write_gemfile
84
+ remove_file target.join('Gemfile')
85
+ template 'util/Gemfile.erb', target.join('Gemfile')
86
+ end
87
+
88
+ def write_rakefile
89
+ remove_file target.join('Rakefile')
90
+ template 'util/Rakefile.erb', target.join('Rakefile')
91
+ end
92
+
93
+ def write_vagrantfile
94
+ template 'vagrant/Vagrantfile.erb', target.join('Vagrantfile')
95
+ template 'vagrant/init.sh.erb', target.join('.vagrant_puppet/init.sh')
96
+
97
+ # create default puppet environment
98
+ template 'vagrant/environment/environment.conf.erb',
99
+ target.join('.vagrant_puppet/environments/vagrant/environment.conf')
100
+ template 'vagrant/environment/manifests/init.pp.erb',
101
+ target.join('.vagrant_puppet/environments/vagrant/manifests/init.pp')
102
+ end
103
+
104
+ def write_puppet_magnum_init
105
+ remove_file target.join('.puppet-magnum.init')
106
+ template 'puppet-magnum.init.erb', target.join('.puppet-magnum.init')
107
+ end
108
+
109
+ # due to the 'git add' operation, this function should be called last
110
+ def write_git_setup
111
+ remove_file target.join('.gitignore')
112
+ template 'git/gitignore.erb', target.join('.gitignore')
113
+
114
+ unless File.exists?(target.join('.git'))
115
+ inside target do
116
+ run 'git init', capture: true
117
+ run 'git add -A', capture: true
118
+ end
119
+ end
120
+ end
121
+
122
+ private
123
+
124
+ def commented(content)
125
+ content.split("\n").collect { |s| "# #{s}" }.join("\n")
126
+ end
127
+
128
+ def license_name
129
+ case options[:license]
130
+ when 'apachev2'; 'Apache 2.0'
131
+ when 'mit'; 'MIT'
132
+ when 'reserved'; 'All Rights Reserved'
133
+ else
134
+ raise "Unknown license: '#{options[:license]}'"
135
+ end
136
+ end
137
+
138
+ def license
139
+ ERB.new(File.read(File.join(self.class.source_root, license_file))).result(binding)
140
+ end
141
+
142
+ def license_file
143
+ case options[:license]
144
+ when 'apachev2'; 'licenses/apachev2.erb'
145
+ when 'mit'; 'licenses/mit.erb'
146
+ when 'reserved'; 'licenses/reserved.erb'
147
+ else
148
+ raise "Unknown license: '#{options[:license]}'"
149
+ end
150
+ end
151
+
152
+ def which(cmd)
153
+ exts = ENV['PATHEXT'] ? ENV['PATHEXT'].split(';') : ['']
154
+ ENV['PATH'].split(File::PATH_SEPARATOR).each do |path|
155
+ exts.each { |ext|
156
+ exe = File.join(path, "#{cmd}#{ext}")
157
+ return exe if File.executable? exe
158
+ }
159
+ end
160
+ return nil
161
+ end
162
+
163
+ def maintainer
164
+ options[:maintainer]
165
+ end
166
+
167
+ def maintainer_email
168
+ options[:maintainer_email]
169
+ end
170
+
171
+ def copyright_year
172
+ Time.now.year
173
+ end
174
+
175
+ def copyright_holder
176
+ options[:copyright_holder] || maintainer
177
+ end
178
+
179
+ def puppet_magnum_init_timestamp
180
+ "puppet-magnum (#{PuppetMagnum::VERSION.chomp}) last initialized this Puppet module directory on #{Time.now.ctime}."
181
+ end
182
+
183
+ def default_options
184
+ { module_name: module_name }
185
+ end
186
+
187
+ end
188
+ end