vagrant-rimu 0.0.1 → 0.0.6
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 +5 -5
- data/.codeclimate.yml +3 -2
- data/.gitignore +2 -0
- data/.travis.yml +5 -35
- data/Gemfile +4 -2
- data/README.md +12 -3
- data/Rakefile +6 -3
- data/Vagrantfile +12 -3
- data/gemfiles/vagrant_1.5.gemfile +3 -1
- data/gemfiles/vagrant_1.6.gemfile +5 -3
- data/gemfiles/vagrant_1.7.gemfile +10 -8
- data/lib/vagrant-rimu.rb +10 -0
- data/lib/vagrant-rimu/actions.rb +117 -89
- data/lib/vagrant-rimu/actions/abstract_action.rb +20 -0
- data/lib/vagrant-rimu/actions/billing_methods.rb +13 -7
- data/lib/vagrant-rimu/actions/connect_to_rimu.rb +12 -6
- data/lib/vagrant-rimu/actions/create.rb +25 -6
- data/lib/vagrant-rimu/actions/is_created.rb +4 -2
- data/lib/vagrant-rimu/actions/is_stopped.rb +5 -3
- data/lib/vagrant-rimu/actions/list_distributions.rb +13 -7
- data/lib/vagrant-rimu/actions/list_servers.rb +13 -7
- data/lib/vagrant-rimu/actions/message_action_not_supported.rb +19 -0
- data/lib/vagrant-rimu/actions/message_already_created.rb +4 -2
- data/lib/vagrant-rimu/actions/message_already_off.rb +4 -2
- data/lib/vagrant-rimu/actions/message_not_created.rb +4 -2
- data/lib/vagrant-rimu/actions/message_will_not_destroy.rb +4 -2
- data/lib/vagrant-rimu/actions/message_will_not_stop.rb +19 -0
- data/lib/vagrant-rimu/actions/modify_provision_path.rb +5 -3
- data/lib/vagrant-rimu/actions/move.rb +32 -5
- data/lib/vagrant-rimu/actions/read_ssh_info.rb +10 -7
- data/lib/vagrant-rimu/actions/read_state.rb +14 -6
- data/lib/vagrant-rimu/actions/rebuild.rb +34 -6
- data/lib/vagrant-rimu/actions/reload.rb +11 -4
- data/lib/vagrant-rimu/actions/setup_sudo.rb +15 -8
- data/lib/vagrant-rimu/actions/setup_user.rb +45 -25
- data/lib/vagrant-rimu/actions/ssh_utils.rb +44 -0
- data/lib/vagrant-rimu/actions/start_instance.rb +6 -4
- data/lib/vagrant-rimu/actions/stop_instance.rb +18 -7
- data/lib/vagrant-rimu/actions/terminate_instance.rb +12 -6
- data/lib/vagrant-rimu/commands/abstract_command.rb +47 -0
- data/lib/vagrant-rimu/commands/billing_methods.rb +10 -10
- data/lib/vagrant-rimu/commands/distributions.rb +10 -10
- data/lib/vagrant-rimu/commands/list_servers.rb +10 -10
- data/lib/vagrant-rimu/commands/move.rb +10 -10
- data/lib/vagrant-rimu/commands/rebuild.rb +5 -7
- data/lib/vagrant-rimu/commands/rimu_command.rb +13 -0
- data/lib/vagrant-rimu/commands/root.rb +26 -43
- data/lib/vagrant-rimu/commands/utils.rb +22 -0
- data/lib/vagrant-rimu/config.rb +5 -2
- data/lib/vagrant-rimu/errors.rb +6 -0
- data/lib/vagrant-rimu/logging.rb +28 -0
- data/lib/vagrant-rimu/plugin.rb +11 -37
- data/lib/vagrant-rimu/provider.rb +4 -2
- data/lib/vagrant-rimu/version.rb +1 -1
- data/locales/en.yml +70 -19
- data/spec/spec_helper.rb +13 -6
- data/spec/vagrant-rimu/actions/billing_methods_spec.rb +49 -0
- data/spec/vagrant-rimu/actions/connect_to_rimu_spec.rb +2 -1
- data/spec/vagrant-rimu/actions/create_spec.rb +167 -0
- data/spec/vagrant-rimu/actions/is_created_spec.rb +49 -0
- data/spec/vagrant-rimu/actions/is_stopped_spec.rb +49 -0
- data/spec/vagrant-rimu/actions/list_distributions_spec.rb +49 -0
- data/spec/vagrant-rimu/actions/list_servers_spec.rb +51 -0
- data/spec/vagrant-rimu/actions/message_action_not_supported_spec.rb +30 -0
- data/spec/vagrant-rimu/actions/message_already_created_spec.rb +1 -4
- data/spec/vagrant-rimu/actions/message_will_not_destroy_spec.rb +1 -2
- data/spec/vagrant-rimu/actions/message_will_not_stop_spec.rb +35 -0
- data/spec/vagrant-rimu/actions/modify_provision_path_spec.rb +2 -7
- data/spec/vagrant-rimu/actions/move_spec.rb +75 -0
- data/spec/vagrant-rimu/actions/read_ssh_info_spec.rb +21 -0
- data/spec/vagrant-rimu/actions/rebuild_spec.rb +7 -1
- data/spec/vagrant-rimu/actions/stop_instance_spec.rb +4 -4
- data/spec/vagrant-rimu/commands/billing_methods_spec.rb +17 -0
- data/spec/vagrant-rimu/commands/distributions_spec.rb +17 -0
- data/spec/vagrant-rimu/commands/list_servers_spec.rb +17 -0
- data/spec/vagrant-rimu/commands/move_spec.rb +17 -0
- data/spec/vagrant-rimu/commands/rebuild_spec.rb +20 -0
- data/spec/vagrant-rimu/config_spec.rb +1 -1
- data/test/Vagrantfile +4 -2
- data/vagrant-rimu.gemspec +5 -1
- metadata +81 -27
@@ -0,0 +1,20 @@
|
|
1
|
+
require 'colorize'
|
2
|
+
|
3
|
+
module VagrantPlugins
|
4
|
+
module Rimu
|
5
|
+
module Actions
|
6
|
+
class AbstractAction
|
7
|
+
def call(env)
|
8
|
+
execute(env)
|
9
|
+
# rubocop:disable Lint/RescueException
|
10
|
+
rescue Errors::RimuError, SystemExit, Interrupt => e
|
11
|
+
raise e
|
12
|
+
rescue Exception => e
|
13
|
+
puts I18n.t('vagrant_rimu.errors.global_error').red unless e.message && e.message.start_with?('Caught Error:')
|
14
|
+
raise $!, "Caught Error: #{$!}", $!.backtrace
|
15
|
+
end
|
16
|
+
# rubocop:enable Lint/RescueException
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -1,17 +1,23 @@
|
|
1
|
+
require 'vagrant-rimu/commands/utils'
|
2
|
+
require 'vagrant-rimu/actions/abstract_action'
|
3
|
+
|
1
4
|
module VagrantPlugins
|
2
5
|
module Rimu
|
3
6
|
module Actions
|
4
|
-
class BillingMethods
|
5
|
-
|
7
|
+
class BillingMethods < AbstractAction
|
8
|
+
include VagrantPlugins::Rimu::Commands::Utils
|
9
|
+
|
10
|
+
def initialize(app, _env)
|
6
11
|
@app = app
|
7
|
-
@client = env[:rimu_api]
|
8
12
|
end
|
9
13
|
|
10
|
-
def
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
+
def execute(env)
|
15
|
+
rows = []
|
16
|
+
env[:rimu_api].billing_methods.each do |b|
|
17
|
+
rows << [b.billing_oid, b.billing_method_type, b.description]
|
14
18
|
end
|
19
|
+
display_table(env, ['ID', 'Type', 'Description'], rows)
|
20
|
+
|
15
21
|
@app.call(env)
|
16
22
|
end
|
17
23
|
end
|
@@ -1,21 +1,27 @@
|
|
1
1
|
require 'log4r'
|
2
2
|
require 'rimu'
|
3
3
|
|
4
|
+
require 'vagrant-rimu/actions/abstract_action'
|
5
|
+
|
4
6
|
module VagrantPlugins
|
5
7
|
module Rimu
|
6
8
|
module Actions
|
7
|
-
class ConnectToRimu
|
9
|
+
class ConnectToRimu < AbstractAction
|
8
10
|
def initialize(app, env)
|
9
11
|
@app = app
|
10
12
|
@config = env[:machine].provider_config
|
11
13
|
@logger = Log4r::Logger.new('vagrant_rimu::action::connect_to_rimu')
|
12
14
|
end
|
13
15
|
|
14
|
-
def
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
16
|
+
def execute(env)
|
17
|
+
if env[:rimu_api].nil? || ! env[:rimu_api].respond_to?(:api_key)
|
18
|
+
@logger.info('Connecting to Rimu api_url...')
|
19
|
+
rimu = ::Rimu::RimuAPI.new({:api_url => @config.api_url, :api_key=> @config.api_key})
|
20
|
+
env[:rimu_api] = rimu
|
21
|
+
else
|
22
|
+
@logger.info('Not creating a new client object...')
|
23
|
+
end
|
24
|
+
@app.call(env) unless @app.nil?
|
19
25
|
end
|
20
26
|
end
|
21
27
|
end
|
@@ -1,19 +1,25 @@
|
|
1
1
|
require 'log4r'
|
2
2
|
require 'vagrant'
|
3
3
|
|
4
|
+
require 'vagrant-rimu/actions/ssh_utils'
|
5
|
+
require 'vagrant-rimu/actions/abstract_action'
|
6
|
+
|
4
7
|
module VagrantPlugins
|
5
8
|
module Rimu
|
6
9
|
module Actions
|
7
|
-
class Create
|
10
|
+
class Create < AbstractAction
|
8
11
|
include Vagrant::Util::Retryable
|
12
|
+
include VagrantPlugins::Rimu::Actions::SshUtils
|
13
|
+
|
9
14
|
def initialize(app, env)
|
10
15
|
@app = app
|
11
|
-
@client = env[:rimu_api]
|
12
16
|
@machine = env[:machine]
|
13
17
|
@logger = Log4r::Logger.new('vagrant::rimu::create')
|
14
18
|
end
|
15
19
|
|
16
|
-
|
20
|
+
# rubocop:disable Metrics/AbcSize
|
21
|
+
def execute(env)
|
22
|
+
client = env[:rimu_api]
|
17
23
|
env[:ui].info I18n.t('vagrant_rimu.creating')
|
18
24
|
params = {
|
19
25
|
:billing_oid => @machine.provider_config.billing_id,
|
@@ -52,9 +58,16 @@ module VagrantPlugins
|
|
52
58
|
if params.has_key?(:instantiation_options)
|
53
59
|
params[:instantiation_options][:password] = root_pass
|
54
60
|
end
|
55
|
-
|
61
|
+
|
62
|
+
begin
|
63
|
+
result = client.servers.create(params)
|
64
|
+
rescue ::Rimu::RimuAPI::RimuRequestError, ::Rimu::RimuAPI::RimuResponseError => e
|
65
|
+
raise Errors::ApiError, {:stderr=>e}
|
66
|
+
end
|
67
|
+
|
56
68
|
@machine.id = result.order_oid
|
57
69
|
env[:ui].info I18n.t('vagrant_rimu.ip_address', {:ip => result.allocated_ips["primary_ip"]})
|
70
|
+
|
58
71
|
switch_user = @machine.provider_config.setup?
|
59
72
|
user = @machine.config.ssh.username
|
60
73
|
if switch_user
|
@@ -64,12 +77,18 @@ module VagrantPlugins
|
|
64
77
|
if params.has_key?(:instantiation_options)
|
65
78
|
retryable(:tries => 120, :sleep => 10) do
|
66
79
|
next if env[:interrupted]
|
67
|
-
raise 'not ready'
|
80
|
+
raise 'not ready' unless @machine.communicate.ready?
|
68
81
|
end
|
69
82
|
end
|
83
|
+
|
84
|
+
# upload root ssh key
|
85
|
+
upload_key(env)
|
86
|
+
|
70
87
|
@machine.config.ssh.username = user
|
88
|
+
|
71
89
|
@app.call(env)
|
72
90
|
end
|
91
|
+
# rubocop:enable Metrics/AbcSize
|
73
92
|
|
74
93
|
def recover(env)
|
75
94
|
return if env['vagrant.error'].is_a?(Vagrant::Errors::VagrantError)
|
@@ -83,7 +102,7 @@ module VagrantPlugins
|
|
83
102
|
destroy_env.delete(:interrupted)
|
84
103
|
destroy_env[:config_validate] = false
|
85
104
|
destroy_env[:force_confirm_destroy] = true
|
86
|
-
env[:action_runner].run(Actions.
|
105
|
+
env[:action_runner].run(Actions.action_destroy, destroy_env)
|
87
106
|
end
|
88
107
|
end
|
89
108
|
end
|
@@ -1,12 +1,14 @@
|
|
1
|
+
require 'vagrant-rimu/actions/abstract_action'
|
2
|
+
|
1
3
|
module VagrantPlugins
|
2
4
|
module Rimu
|
3
5
|
module Actions
|
4
|
-
class IsCreated
|
6
|
+
class IsCreated < AbstractAction
|
5
7
|
def initialize(app, _env)
|
6
8
|
@app = app
|
7
9
|
end
|
8
10
|
|
9
|
-
def
|
11
|
+
def execute(env)
|
10
12
|
env[:result] = env[:machine].state.id != :not_created
|
11
13
|
@app.call(env)
|
12
14
|
end
|
@@ -1,13 +1,15 @@
|
|
1
|
+
require 'vagrant-rimu/actions/abstract_action'
|
2
|
+
|
1
3
|
module VagrantPlugins
|
2
4
|
module Rimu
|
3
5
|
module Actions
|
4
|
-
class IsStopped
|
6
|
+
class IsStopped < AbstractAction
|
5
7
|
def initialize(app, _env)
|
6
8
|
@app = app
|
7
9
|
end
|
8
10
|
|
9
|
-
def
|
10
|
-
env[:result] = env[:machine].state.id == :
|
11
|
+
def execute(env)
|
12
|
+
env[:result] = env[:machine].state.id == :off
|
11
13
|
|
12
14
|
@app.call(env)
|
13
15
|
end
|
@@ -1,17 +1,23 @@
|
|
1
|
+
require 'vagrant-rimu/commands/utils'
|
2
|
+
require 'vagrant-rimu/actions/abstract_action'
|
3
|
+
|
1
4
|
module VagrantPlugins
|
2
5
|
module Rimu
|
3
6
|
module Actions
|
4
|
-
class ListDistributions
|
5
|
-
|
7
|
+
class ListDistributions < AbstractAction
|
8
|
+
include VagrantPlugins::Rimu::Commands::Utils
|
9
|
+
|
10
|
+
def initialize(app, _env)
|
6
11
|
@app = app
|
7
|
-
@client = env[:rimu_api]
|
8
12
|
end
|
9
13
|
|
10
|
-
def
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
+
def execute(env)
|
15
|
+
rows = []
|
16
|
+
env[:rimu_api].distributions.each do |dist|
|
17
|
+
rows << [dist.distro_code, dist.distro_description]
|
14
18
|
end
|
19
|
+
display_table(env, ['Distro Code', 'Distro Description'], rows)
|
20
|
+
|
15
21
|
@app.call(env)
|
16
22
|
end
|
17
23
|
end
|
@@ -1,17 +1,23 @@
|
|
1
|
+
require 'vagrant-rimu/commands/utils'
|
2
|
+
require 'vagrant-rimu/actions/abstract_action'
|
3
|
+
|
1
4
|
module VagrantPlugins
|
2
5
|
module Rimu
|
3
6
|
module Actions
|
4
|
-
class ListServers
|
5
|
-
|
7
|
+
class ListServers < AbstractAction
|
8
|
+
include VagrantPlugins::Rimu::Commands::Utils
|
9
|
+
|
10
|
+
def initialize(app, _env)
|
6
11
|
@app = app
|
7
|
-
@client = env[:rimu_api]
|
8
12
|
end
|
9
13
|
|
10
|
-
def
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
+
def execute(env)
|
15
|
+
rows = []
|
16
|
+
env[:rimu_api].orders.orders.each do |o|
|
17
|
+
rows << [o.order_oid, o.domain_name, o.location["data_center_location_code"], o.host_server_oid, o.running_state]
|
14
18
|
end
|
19
|
+
display_table(env, ['ID', 'Hostname', 'Data Centre', 'Host Server', 'Status'], rows)
|
20
|
+
|
15
21
|
@app.call(env)
|
16
22
|
end
|
17
23
|
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
require 'vagrant-rimu/actions/abstract_action'
|
2
|
+
|
3
|
+
module VagrantPlugins
|
4
|
+
module Rimu
|
5
|
+
module Actions
|
6
|
+
class MessageActionNotSupported < AbstractAction
|
7
|
+
def initialize(app, _env)
|
8
|
+
@app = app
|
9
|
+
end
|
10
|
+
|
11
|
+
def execute(env)
|
12
|
+
env[:ui].info(I18n.t('vagrant_rimu.action_not_supported'))
|
13
|
+
|
14
|
+
@app.call(env)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -1,12 +1,14 @@
|
|
1
|
+
require 'vagrant-rimu/actions/abstract_action'
|
2
|
+
|
1
3
|
module VagrantPlugins
|
2
4
|
module Rimu
|
3
5
|
module Actions
|
4
|
-
class MessageAlreadyCreated
|
6
|
+
class MessageAlreadyCreated < AbstractAction
|
5
7
|
def initialize(app, _env)
|
6
8
|
@app = app
|
7
9
|
end
|
8
10
|
|
9
|
-
def
|
11
|
+
def execute(env)
|
10
12
|
env[:ui].info(I18n.t('vagrant_rimu.already_status', :status => 'created'))
|
11
13
|
@app.call(env)
|
12
14
|
end
|
@@ -1,12 +1,14 @@
|
|
1
|
+
require 'vagrant-rimu/actions/abstract_action'
|
2
|
+
|
1
3
|
module VagrantPlugins
|
2
4
|
module Rimu
|
3
5
|
module Actions
|
4
|
-
class MessageAlreadyOff
|
6
|
+
class MessageAlreadyOff < AbstractAction
|
5
7
|
def initialize(app, _env)
|
6
8
|
@app = app
|
7
9
|
end
|
8
10
|
|
9
|
-
def
|
11
|
+
def execute(env)
|
10
12
|
env[:ui].info(I18n.t("vagrant_rimu.already_status", :status => :off))
|
11
13
|
@app.call(env)
|
12
14
|
end
|
@@ -1,12 +1,14 @@
|
|
1
|
+
require 'vagrant-rimu/actions/abstract_action'
|
2
|
+
|
1
3
|
module VagrantPlugins
|
2
4
|
module Rimu
|
3
5
|
module Actions
|
4
|
-
class MessageNotCreated
|
6
|
+
class MessageNotCreated < AbstractAction
|
5
7
|
def initialize(app, _env)
|
6
8
|
@app = app
|
7
9
|
end
|
8
10
|
|
9
|
-
def
|
11
|
+
def execute(env)
|
10
12
|
env[:ui].info(I18n.t('vagrant_rimu.not_created'))
|
11
13
|
@app.call(env)
|
12
14
|
end
|
@@ -1,13 +1,15 @@
|
|
1
|
+
require 'vagrant-rimu/actions/abstract_action'
|
2
|
+
|
1
3
|
module VagrantPlugins
|
2
4
|
module Rimu
|
3
5
|
module Actions
|
4
|
-
class MessageWillNotDestroy
|
6
|
+
class MessageWillNotDestroy < AbstractAction
|
5
7
|
def initialize(app, env)
|
6
8
|
@app = app
|
7
9
|
@machine = env[:machine]
|
8
10
|
end
|
9
11
|
|
10
|
-
def
|
12
|
+
def execute(env)
|
11
13
|
env[:ui].info(I18n.t('vagrant_rimu.will_not_destroy', {:name => @machine.name}))
|
12
14
|
@app.call(env)
|
13
15
|
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
require 'vagrant-rimu/actions/abstract_action'
|
2
|
+
|
3
|
+
module VagrantPlugins
|
4
|
+
module Rimu
|
5
|
+
module Actions
|
6
|
+
class MessageWillNotStop < AbstractAction
|
7
|
+
def initialize(app, env)
|
8
|
+
@app = app
|
9
|
+
@machine = env[:machine]
|
10
|
+
end
|
11
|
+
|
12
|
+
def execute(env)
|
13
|
+
env[:ui].info(I18n.t('vagrant_rimu.will_not_stop', {:name => @machine.name}))
|
14
|
+
@app.call(env)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -1,20 +1,22 @@
|
|
1
1
|
require 'log4r'
|
2
2
|
|
3
|
+
require 'vagrant-rimu/actions/abstract_action'
|
4
|
+
|
3
5
|
module VagrantPlugins
|
4
6
|
module Rimu
|
5
7
|
module Actions
|
6
|
-
class ModifyProvisionPath
|
8
|
+
class ModifyProvisionPath < AbstractAction
|
7
9
|
def initialize(app, env)
|
8
10
|
@app = app
|
9
11
|
@machine = env[:machine]
|
10
12
|
@logger = Log4r::Logger.new('vagrant::rimu::modify_provision_path')
|
11
13
|
end
|
12
14
|
|
13
|
-
def
|
15
|
+
def execute(env)
|
14
16
|
# check if provisioning is enabled
|
15
17
|
enabled = true
|
16
18
|
enabled = env[:provision_enabled] if env.has_key?(:provision_enabled)
|
17
|
-
return @app.call(env)
|
19
|
+
return @app.call(env) unless enabled
|
18
20
|
|
19
21
|
username = @machine.ssh_info()[:username]
|
20
22
|
|
@@ -1,19 +1,46 @@
|
|
1
1
|
require 'log4r'
|
2
|
+
require 'vagrant'
|
3
|
+
|
4
|
+
require 'vagrant-rimu/actions/abstract_action'
|
2
5
|
|
3
6
|
module VagrantPlugins
|
4
7
|
module Rimu
|
5
8
|
module Actions
|
6
|
-
class Move
|
9
|
+
class Move < AbstractAction
|
10
|
+
include Vagrant::Util::Retryable
|
11
|
+
|
7
12
|
def initialize(app, env)
|
8
13
|
@app = app
|
9
14
|
@machine = env[:machine]
|
10
|
-
@client = client
|
11
15
|
@logger = Log4r::Logger.new('vagrant::rimu::move')
|
12
16
|
end
|
13
17
|
|
14
|
-
|
15
|
-
|
16
|
-
|
18
|
+
# rubocop:disable Metrics/AbcSize
|
19
|
+
def execute(env)
|
20
|
+
client = env[:rimu_api]
|
21
|
+
|
22
|
+
env[:ui].info I18n.t('vagrant_rimu.moving')
|
23
|
+
|
24
|
+
begin
|
25
|
+
result = client.servers.move(@machine.id.to_i)
|
26
|
+
rescue ::Rimu::RimuAPI::RimuRequestError, ::Rimu::RimuAPI::RimuResponseError => e
|
27
|
+
raise Errors::ApiError, {:stderr=>e}
|
28
|
+
end
|
29
|
+
|
30
|
+
@machine.id = result.order_oid
|
31
|
+
env[:ui].info I18n.t('vagrant_rimu.ip_address', {:ip => result.allocated_ips["primary_ip"]})
|
32
|
+
|
33
|
+
switch_user = @machine.provider_config.setup?
|
34
|
+
user = @machine.config.ssh.username
|
35
|
+
@machine.config.ssh.username = 'root' if switch_user
|
36
|
+
|
37
|
+
retryable(:tries => 120, :sleep => 10) do
|
38
|
+
next if env[:interrupted]
|
39
|
+
raise 'not ready' unless @machine.communicate.ready?
|
40
|
+
end
|
41
|
+
|
42
|
+
@machine.config.ssh.username = user
|
43
|
+
|
17
44
|
@app.call(env)
|
18
45
|
end
|
19
46
|
end
|