vagrant_abiquo 0.0.8 → 0.1.0

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: 9204419a82ee1a7ad3e2b447e2ae7cdc0be0ac34
4
- data.tar.gz: 8ba5d4eacb15ee24ee8cbab7ac993244c10a523d
3
+ metadata.gz: ebfd2778cc1f2fb46b9f4a67a98f74ba6894bf47
4
+ data.tar.gz: 3b7c3adc0ff0d1762dded68cb7716cc79b42bf73
5
5
  SHA512:
6
- metadata.gz: b166481d7d44b0113d595693909bf28bfc409377458989796e6baf3283ea98606cfe4e0e706e750f7101ec47f284ed189fbfd2cb686bb448c6a01de07b1ea44b
7
- data.tar.gz: 26132721e2f649d26c1f317e0e6785915d5364129c90983cab9c3180cb7ceca056c94d91d82ab5749408562001e9a3c8a8ce8e0f91a9d8b8089db723b97b3d60
6
+ metadata.gz: fd47d96785ed490c9f545506af10ae21d61467b3bb6136cddb2bd4a02d4690b413eb9cd6f1452951a7d705b95feaea382666d2905e2ea2d8370c04eff63aec19
7
+ data.tar.gz: 25d3b0caecfe86e5b688356a0cf2e5260e86eabedda3bfb4dd11eb14f7544a1bdccd0beadade8512256eaed8f51b155004bc7710ddb18a1eada686379d204516
data/Gemfile.lock CHANGED
@@ -1,18 +1,17 @@
1
1
  GIT
2
2
  remote: https://github.com/mitchellh/vagrant.git
3
- revision: 96368d8a1f778761e74433b83502f119610a6647
3
+ revision: 40d5c28f3f16d446b9bb57153fc6bc5ee8522d77
4
4
  specs:
5
- vagrant (1.9.2.dev)
6
- childprocess (~> 0.5.0)
5
+ vagrant (1.9.8.dev)
6
+ childprocess (~> 0.6.0)
7
7
  erubis (~> 2.7.0)
8
8
  hashicorp-checkpoint (~> 0.1.1)
9
9
  i18n (>= 0.6.0, <= 0.8.0)
10
10
  listen (~> 3.1.5)
11
11
  log4r (~> 1.1.9, < 1.1.11)
12
- net-scp (~> 1.1.0)
12
+ net-scp (~> 1.2.0)
13
13
  net-sftp (~> 2.1)
14
- net-ssh (~> 3.0.1)
15
- nokogiri (= 1.6.7.1)
14
+ net-ssh (~> 4.1.0)
16
15
  rb-kqueue (~> 0.2.0)
17
16
  rest-client (>= 1.6.0, < 3.0)
18
17
  ruby_dep (<= 1.3.1)
@@ -24,7 +23,7 @@ GIT
24
23
  PATH
25
24
  remote: .
26
25
  specs:
27
- vagrant_abiquo (0.0.8)
26
+ vagrant_abiquo (0.1.0)
28
27
  abiquo-api (~> 0.1.2)
29
28
  log4r
30
29
 
@@ -39,22 +38,22 @@ GEM
39
38
  formatador (~> 0.2, >= 0.2.5)
40
39
  json
41
40
  simple_oauth (~> 0.3.1, >= 0.3.1)
42
- addressable (2.5.0)
41
+ addressable (2.5.1)
43
42
  public_suffix (~> 2.0, >= 2.0.2)
44
43
  builder (3.2.3)
45
44
  byebug (9.0.6)
46
- childprocess (0.5.9)
45
+ childprocess (0.6.3)
47
46
  ffi (~> 1.0, >= 1.0.11)
48
47
  coderay (1.1.1)
49
- domain_name (0.5.20161129)
48
+ domain_name (0.5.20170404)
50
49
  unf (>= 0.0.5, < 1.0.0)
51
50
  erubis (2.7.0)
52
- excon (0.55.0)
51
+ excon (0.58.0)
53
52
  faraday (0.9.2)
54
53
  multipart-post (>= 1.2, < 3)
55
54
  faraday_middleware (0.10.1)
56
55
  faraday (>= 0.7.4, < 1.0)
57
- ffi (1.9.17)
56
+ ffi (1.9.18)
58
57
  formatador (0.2.5)
59
58
  gssapi (1.2.0)
60
59
  ffi (>= 1.0.1)
@@ -65,31 +64,28 @@ GEM
65
64
  domain_name (~> 0.5)
66
65
  httpclient (2.8.3)
67
66
  i18n (0.8.0)
68
- json (2.0.3)
67
+ json (2.1.0)
69
68
  listen (3.1.5)
70
69
  rb-fsevent (~> 0.9, >= 0.9.4)
71
70
  rb-inotify (~> 0.9, >= 0.9.7)
72
71
  ruby_dep (~> 1.2)
73
72
  little-plugger (1.1.4)
74
73
  log4r (1.1.10)
75
- logging (2.1.0)
74
+ logging (2.2.2)
76
75
  little-plugger (~> 1.1)
77
76
  multi_json (~> 1.10)
78
77
  method_source (0.8.2)
79
78
  mime-types (3.1)
80
79
  mime-types-data (~> 3.2015)
81
80
  mime-types-data (3.2016.0521)
82
- mini_portile2 (2.0.0)
83
81
  multi_json (1.12.1)
84
82
  multipart-post (2.0.0)
85
- net-scp (1.1.2)
83
+ net-scp (1.2.1)
86
84
  net-ssh (>= 2.6.5)
87
85
  net-sftp (2.1.2)
88
86
  net-ssh (>= 2.6.5)
89
- net-ssh (3.0.2)
87
+ net-ssh (4.1.0)
90
88
  netrc (0.11.0)
91
- nokogiri (1.6.7.1)
92
- mini_portile2 (~> 2.0.0.rc2)
93
89
  nori (2.6.0)
94
90
  pry (0.10.4)
95
91
  coderay (~> 1.1.0)
@@ -100,25 +96,25 @@ GEM
100
96
  pry (~> 0.10)
101
97
  public_suffix (2.0.5)
102
98
  rake (12.0.0)
103
- rb-fsevent (0.9.8)
104
- rb-inotify (0.9.8)
99
+ rb-fsevent (0.10.2)
100
+ rb-inotify (0.9.10)
101
+ ffi (>= 0.5.0, < 2)
102
+ rb-kqueue (0.2.5)
105
103
  ffi (>= 0.5.0)
106
- rb-kqueue (0.2.4)
107
- ffi (>= 0.5.0)
108
- rest-client (2.0.0)
104
+ rest-client (2.0.2)
109
105
  http-cookie (>= 1.0.2, < 2.0)
110
106
  mime-types (>= 1.16, < 4.0)
111
107
  netrc (~> 0.8)
112
108
  ruby_dep (1.3.1)
113
- rubyntlm (0.6.1)
109
+ rubyntlm (0.6.2)
114
110
  rubyzip (1.2.1)
115
111
  simple_oauth (0.3.1)
116
112
  slop (3.6.0)
117
113
  unf (0.1.4)
118
114
  unf_ext
119
- unf_ext (0.0.7.2)
115
+ unf_ext (0.0.7.4)
120
116
  wdm (0.1.1)
121
- winrm (2.1.2)
117
+ winrm (2.2.3)
122
118
  builder (>= 2.1.2)
123
119
  erubis (~> 2.7)
124
120
  gssapi (~> 1.2)
data/Rakefile CHANGED
@@ -15,8 +15,3 @@ task :test do
15
15
  end
16
16
  end
17
17
 
18
- def env
19
- ['ABIQUO_API_USER', 'ABIQUO_API_PASSWORD', 'VAGRANT_LOG'].inject('') do |acc, key|
20
- acc += "#{key}=#{ENV[key] || 'error'} "
21
- end
22
- end
data/Vagrantfile CHANGED
@@ -3,10 +3,16 @@ VAGRANTFILE_API_VERSION = "2"
3
3
  Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
4
4
  config.vm.synced_folder ".", "/vagrant", type: "rsync"
5
5
 
6
- config.vm.define "abiquosingle"
6
+ config.vm.define "abiquosingle" do |abq|
7
+ abq.vm.provision "shell",
8
+ inline: "echo Hello, World"
9
+ end
7
10
 
8
- #(1..10).each do |ind|
9
- # config.vm.define "abiquotesting-#{ind}"
11
+ #(1..3).each do |ind|
12
+ # config.vm.define "abiquotesting-#{ind}" do |vm|
13
+ # vm.vm.provision "shell",
14
+ # inline: "echo Hello, $(hostname)"
15
+ # end
10
16
  #end
11
17
 
12
18
  config.vm.provider :abiquo do |provider, override|
@@ -15,7 +21,7 @@ Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
15
21
  override.vm.hostname = 'abiquotesting'
16
22
 
17
23
  provider.abiquo_connection_data = {
18
- abiquo_api_url: 'https://chirauki40.bcn.abiquo.com/api',
24
+ abiquo_api_url: 'https://chirauki401.bcn.abiquo.com/api',
19
25
  abiquo_username: 'admin',
20
26
  abiquo_password: 'xabiquo',
21
27
  connection_options: {
@@ -24,14 +30,13 @@ Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
24
30
  }
25
31
  }
26
32
  }
27
- provider.cpu_cores = 1
28
- provider.ram_mb = 512
29
- #provider.hwprofile = '4gb'
30
- provider.virtualdatacenter = 'esx'
33
+ #provider.cpu_cores = 1
34
+ #provider.ram_mb = 512
35
+ provider.hwprofile = 'A0'
36
+ provider.virtualdatacenter = 'ESX'
31
37
  provider.virtualappliance = 'Vagrant Tests'
32
38
  provider.template = 'Centos 7 x86_64'
33
39
 
34
40
  override.ssh.private_key_path = '~/.ssh/id_rsa'
35
- override.ssh.username = 'centos'
36
41
  end
37
42
  end
@@ -1,6 +1,5 @@
1
1
  require 'pathname'
2
2
  require 'vagrant_abiquo/plugin'
3
- require 'vagrant_abiquo/helpers/client'
4
3
 
5
4
  module VagrantPlugins
6
5
  module Abiquo
@@ -11,8 +10,5 @@ module VagrantPlugins
11
10
  def self.source_root
12
11
  @source_root ||= Pathname.new(File.expand_path('../../', __FILE__))
13
12
  end
14
-
15
- I18n.load_path << File.expand_path('locales/en.yml', source_root)
16
- I18n.reload!
17
13
  end
18
14
  end
@@ -1,63 +1,67 @@
1
- require 'vagrant_abiquo/actions/check_state'
2
- require 'vagrant_abiquo/actions/create'
3
- require 'vagrant_abiquo/actions/deploy'
4
- require 'vagrant_abiquo/actions/destroy'
5
- require 'vagrant_abiquo/actions/power_off'
6
- require 'vagrant_abiquo/actions/power_on'
7
- require 'vagrant_abiquo/actions/reset'
8
-
9
1
  module VagrantPlugins
10
2
  module Abiquo
11
3
  module Actions
12
4
  include Vagrant::Action::Builtin
13
5
 
14
- def self.destroy
6
+ def self.action_destroy
15
7
  return Vagrant::Action::Builder.new.tap do |builder|
16
8
  builder.use ConfigValidate
9
+ builder.use Connect
17
10
  builder.use Call, CheckState do |env, b|
18
11
  case env[:machine_state]
19
12
  when :not_created
20
13
  env[:ui].info I18n.t('vagrant_abiquo.info.not_created')
21
- else
14
+ when :ON, :OFF
22
15
  b.use Call, DestroyConfirm do |env2, b2|
23
16
  if env2[:result]
24
17
  b2.use ProvisionerCleanup, :before if defined?(ProvisionerCleanup)
25
18
  b2.use Destroy
19
+ b2.use DeletevApp
26
20
  end
27
21
  end
22
+ else
23
+ raise Abiquo::Errors::InvalidStateError, vm: env[:machine].name.to_s, state: env[:machine_state]
28
24
  end
29
25
  end
30
26
  end
31
27
  end
32
28
 
33
- def self.up
29
+ def self.action_up
34
30
  return Vagrant::Action::Builder.new.tap do |builder|
35
31
  builder.use ConfigValidate
32
+ builder.use Connect
36
33
  builder.use Call, CheckState do |env, b|
37
34
  case env[:machine_state]
38
35
  when :ON
39
36
  env[:ui].info I18n.t('vagrant_abiquo.info.already_active')
40
37
  when :OFF
41
38
  b.use PowerOn
39
+ b.use WaitForCommunicator
42
40
  b.use Provision
43
41
  b.use SyncedFolders
44
42
  when :not_created
43
+ b.use CreatevApp
45
44
  b.use Create
46
45
  b.use Deploy
46
+ b.use WaitForCommunicator
47
47
  b.use Provision
48
48
  b.use SyncedFolders
49
49
  when :NOT_ALLOCATED
50
50
  b.use Deploy
51
+ b.use WaitForCommunicator
51
52
  b.use Provision
52
53
  b.use SyncedFolders
54
+ else
55
+ raise Abiquo::Errors::InvalidStateError, vm: env[:machine].name.to_s, state: env[:machine_state]
53
56
  end
54
57
  end
55
58
  end
56
59
  end
57
60
 
58
- def self.reload
61
+ def self.action_reload
59
62
  return Vagrant::Action::Builder.new.tap do |builder|
60
63
  builder.use ConfigValidate
64
+ builder.use Connect
61
65
  builder.use Call, CheckState do |env, b|
62
66
  case env[:machine_state]
63
67
  when :not_created
@@ -69,9 +73,10 @@ module VagrantPlugins
69
73
  end
70
74
  end
71
75
 
72
- def self.halt
76
+ def self.action_halt
73
77
  return Vagrant::Action::Builder.new.tap do |builder|
74
78
  builder.use ConfigValidate
79
+ builder.use Connect
75
80
  builder.use Call, CheckState do |env, b|
76
81
  case env[:machine_state]
77
82
  when :ON
@@ -85,9 +90,10 @@ module VagrantPlugins
85
90
  end
86
91
  end
87
92
 
88
- def self.ssh
93
+ def self.action_ssh
89
94
  return Vagrant::Action::Builder.new.tap do |builder|
90
95
  builder.use ConfigValidate
96
+ builder.use Connect
91
97
  builder.use Call, CheckState do |env, b|
92
98
  case env[:machine_state]
93
99
  when :ON
@@ -101,9 +107,10 @@ module VagrantPlugins
101
107
  end
102
108
  end
103
109
 
104
- def self.ssh_run
110
+ def self.action_ssh_run
105
111
  return Vagrant::Action::Builder.new.tap do |builder|
106
112
  builder.use ConfigValidate
113
+ builder.use Connect
107
114
  builder.use Call, CheckState do |env, b|
108
115
  case env[:machine_state]
109
116
  when :ON
@@ -117,23 +124,53 @@ module VagrantPlugins
117
124
  end
118
125
  end
119
126
 
120
- def self.provision
127
+ def self.action_provision
121
128
  return Vagrant::Action::Builder.new.tap do |builder|
122
129
  builder.use ConfigValidate
130
+ builder.use Connect
123
131
  builder.use Call, CheckState do |env, b|
124
132
  case env[:machine_state]
125
- when :ON
126
- b.use Provision
127
- b.use SyncedFolders
128
133
  when :OFF
129
134
  env[:ui].info I18n.t('vagrant_abiquo.info.off')
130
135
  when :not_created
131
136
  env[:ui].info I18n.t('vagrant_abiquo.info.not_created')
137
+ when :ON
138
+ b.use Provision
139
+ b.use SyncedFolders
132
140
  end
133
141
  end
134
142
  end
135
143
  end
136
144
 
145
+ def self.action_check_state
146
+ return Vagrant::Action::Builder.new.tap do |builder|
147
+ builder.use ConfigValidate
148
+ builder.use Connect
149
+ builder.use CheckState
150
+ end
151
+ end
152
+
153
+ def self.action_read_ssh_info
154
+ return Vagrant::Action::Builder.new.tap do |builder|
155
+ builder.use ConfigValidate
156
+ builder.use Connect
157
+ builder.use ReadSSHInfo
158
+ end
159
+ end
160
+
161
+ # The autoload farm
162
+ action_root = Pathname.new(File.expand_path("../actions", __FILE__))
163
+ autoload :Connect, action_root.join("connect")
164
+ autoload :CheckState, action_root.join("check_state")
165
+ autoload :CreatevApp, action_root.join("create_vapp")
166
+ autoload :Create, action_root.join("create")
167
+ autoload :Deploy, action_root.join("deploy")
168
+ autoload :Destroy, action_root.join("destroy")
169
+ autoload :DeletevApp, action_root.join("delete_vapp")
170
+ autoload :PowerOff, action_root.join("power_off")
171
+ autoload :PowerOn, action_root.join("power_on")
172
+ autoload :ReadSSHInfo, action_root.join("read_ssh_info")
173
+ autoload :Reset, action_root.join("reset")
137
174
  end
138
175
  end
139
176
  end
@@ -1,12 +1,9 @@
1
- require 'vagrant_abiquo/helpers/client'
2
1
  require 'vagrant_abiquo/helpers/abiquo'
3
2
 
4
3
  module VagrantPlugins
5
4
  module Abiquo
6
5
  module Actions
7
- class CheckState
8
- include Helpers::Client
9
-
6
+ class CheckState
10
7
  def initialize(app, env)
11
8
  @app = app
12
9
  @machine = env[:machine]
@@ -14,8 +11,29 @@ module VagrantPlugins
14
11
  end
15
12
 
16
13
  def call(env)
17
- env[:machine_state] = @machine.state.id
18
- @logger.info "Machine state is '#{@machine.state.id}'"
14
+ vapp_name = @machine.provider_config.virtualappliance.nil? ? File.basename(@machine.env.cwd) : @machine.provider_config.virtualappliance
15
+
16
+ # If machine ID is nil try to lookup by name
17
+ if @machine.id.nil?
18
+ vms_lnk = AbiquoAPI::Link.new :href => 'cloud/virtualmachines',
19
+ :type => 'application/vnd.abiquo.virtualmachines+json',
20
+ :client => env[:abiquo_client]
21
+ @vm = vms_lnk.get.select {|v| v.label == @machine.name.to_s and
22
+ v.link(:virtualappliance).title == vapp_name }.first
23
+ @machine.id = @vm.url unless @vm.nil?
24
+ else
25
+ # ID is the URL of the VM
26
+ begin
27
+ vm_lnk = AbiquoAPI::Link.new :href => @machine.id,
28
+ :type => 'application/vnd.abiquo.virtualmachine+json',
29
+ :client => env[:abiquo_client]
30
+ @vm = vm_lnk.get
31
+ rescue AbiquoAPIClient::NotFound
32
+ nil
33
+ end
34
+ end
35
+ env[:machine_state] = @vm.nil? ? :not_created : @vm.state.to_sym
36
+ @logger.info "Machine state is '#{env[:machine_state]}'"
19
37
  @app.call(env)
20
38
  end
21
39
  end
@@ -0,0 +1,23 @@
1
+ require 'abiquo-api'
2
+
3
+ module VagrantPlugins
4
+ module Abiquo
5
+ module Actions
6
+ class Connect
7
+ def initialize(app, env)
8
+ @app = app
9
+ @machine = env[:machine]
10
+ @env = env
11
+ @logger = Log4r::Logger.new('vagrant::abiquo::connect')
12
+ end
13
+
14
+ def call(env)
15
+ client ||= AbiquoAPI.new(@machine.provider_config.abiquo_connection_data)
16
+ env[:abiquo_client] = client
17
+
18
+ @app.call(env)
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
@@ -1,25 +1,23 @@
1
- require 'vagrant_abiquo/helpers/client'
2
1
  require 'vagrant_abiquo/helpers/abiquo'
3
2
 
4
3
  module VagrantPlugins
5
4
  module Abiquo
6
5
  module Actions
7
6
  class Create
8
- include Helpers::Client
9
7
  include Helpers::Abiquo
10
- include Vagrant::Util::Retryable
11
8
 
12
9
  def initialize(app, env)
13
10
  @app = app
14
11
  @machine = env[:machine]
15
- @client = client
16
12
  @env = env
17
13
  @logger = Log4r::Logger.new('vagrant::abiquo::create')
18
14
  end
19
15
 
20
16
  def call(env)
17
+ client = env[:abiquo_client]
18
+
21
19
  # Find for selected virtual datacenter
22
- vdc = get_vdc(@machine.provider_config.virtualdatacenter)
20
+ vdc = get_vdc(client, @machine.provider_config.virtualdatacenter)
23
21
  raise Abiquo::Errors::VDCNotFound, vdc: @machine.provider_config.virtualdatacenter if vdc.nil?
24
22
 
25
23
  # Check if we have to use hwprofiles
@@ -69,7 +67,7 @@ module VagrantPlugins
69
67
 
70
68
  # Create VM
71
69
  env[:ui].info I18n.t('vagrant_abiquo.info.create')
72
- vm = create_vm(vm_definition, vapp)
70
+ vm = create_vm(client, vm_definition, vapp)
73
71
 
74
72
  # User Data
75
73
  md = vm.link(:metadata).get
@@ -79,13 +77,13 @@ module VagrantPlugins
79
77
  else
80
78
  mdhash['metadata']['startup-script'] = @machine.provider_config.user_data
81
79
  end
82
- @client.put(vm.link(:metadata), mdhash.to_json)
80
+ client.put(vm.link(:metadata), mdhash.to_json)
83
81
 
84
82
  # Check network
85
83
  unless @machine.provider_config.network.nil?
86
84
  # Network config is not nil, so we have
87
85
  # to attach a specific net.
88
- attach_net(vm, @machine.provider_config.network)
86
+ attach_net(client, vm, @machine.provider_config.network)
89
87
  raise Abiquo::Errors::NetworkError if vm.nil?
90
88
  end
91
89
  vm = vm.link(:edit).get
@@ -93,24 +91,6 @@ module VagrantPlugins
93
91
 
94
92
  @app.call(env)
95
93
  end
96
-
97
- # Both the recover and terminate are stolen almost verbatim from
98
- # the Vagrant AWS provider up action
99
- def recover(env)
100
- return if env['vagrant.error'].is_a?(Vagrant::Errors::VagrantError)
101
-
102
- if @machine.state.id != :not_created
103
- terminate(env)
104
- end
105
- end
106
-
107
- def terminate(env)
108
- destroy_env = env.dup
109
- destroy_env.delete(:interrupted)
110
- destroy_env[:config_validate] = false
111
- destroy_env[:force_confirm_destroy] = true
112
- env[:action_runner].run(Actions.destroy, destroy_env)
113
- end
114
94
  end
115
95
  end
116
96
  end
@@ -1,11 +1,9 @@
1
- require 'vagrant_abiquo/helpers/client'
2
1
  require 'vagrant_abiquo/helpers/abiquo'
3
2
 
4
3
  module VagrantPlugins
5
4
  module Abiquo
6
5
  module Actions
7
6
  class CreatevApp
8
- include Helpers::Client
9
7
  include Helpers::Abiquo
10
8
 
11
9
  def initialize(app, env)
@@ -15,22 +13,23 @@ module VagrantPlugins
15
13
  end
16
14
 
17
15
  def call(env)
18
- if env[:env].vagrantfile.config.finalize![:vm].respond_to? :get_provider_config
19
- pconfig = env[:env].vagrantfile.config.finalize![:vm].get_provider_config(:abiquo)
20
- return if pconfig.abiquo_connection_data.nil?
21
- end
22
- @client ||= AbiquoAPI.new(pconfig.abiquo_connection_data)
16
+ if @machine.provider_config.class == VagrantPlugins::Abiquo::Config
17
+ client = env[:abiquo_client]
18
+
19
+ pconfig = @machine.provider_config
20
+
21
+ @logger.info "Checking vApp '#{pconfig.virtualappliance}'"
23
22
 
24
- @logger.info "Checking vApp '#{pconfig.virtualappliance}'"
23
+ @logger.info "Looking up VDC '#{pconfig.virtualdatacenter}'"
25
24
 
26
- @logger.info "Looking up VDC '#{pconfig.virtualdatacenter}'"
27
- vdc = get_vdc(pconfig.virtualdatacenter)
28
- raise Abiquo::Errors::VDCNotFound, vdc: pconfig.virtualdatacenter if vdc.nil?
25
+ vdc = get_vdc(client, pconfig.virtualdatacenter)
26
+ raise Abiquo::Errors::VDCNotFound, vdc: pconfig.virtualdatacenter if vdc.nil?
29
27
 
30
- vapp = get_vapp(vdc, pconfig.virtualappliance)
31
- if vapp.nil?
32
- @logger.info "vApp '#{pconfig.virtualappliance}' does not exist, creating."
33
- create_vapp(vdc, pconfig.virtualappliance)
28
+ vapp = get_vapp(vdc, pconfig.virtualappliance)
29
+ if vapp.nil?
30
+ @logger.info "vApp '#{pconfig.virtualappliance}' does not exist, creating."
31
+ create_vapp(client, vdc, pconfig.virtualappliance)
32
+ end
34
33
  end
35
34
 
36
35
  @app.call(env)
@@ -1,11 +1,9 @@
1
- require 'vagrant_abiquo/helpers/client'
2
1
  require 'vagrant_abiquo/helpers/abiquo'
3
2
 
4
3
  module VagrantPlugins
5
4
  module Abiquo
6
5
  module Actions
7
6
  class DeletevApp
8
- include Helpers::Client
9
7
  include Helpers::Abiquo
10
8
 
11
9
  def initialize(app, env)
@@ -15,22 +13,22 @@ module VagrantPlugins
15
13
  end
16
14
 
17
15
  def call(env)
18
- if env[:env].vagrantfile.config.finalize![:vm].respond_to? :get_provider_config
19
- pconfig = env[:env].vagrantfile.config.finalize![:vm].get_provider_config(:abiquo)
20
- return if pconfig.abiquo_connection_data.nil?
21
- end
22
- @client ||= AbiquoAPI.new(pconfig.abiquo_connection_data)
16
+ if @machine.provider_config.class == VagrantPlugins::Abiquo::Config
17
+ client = env[:abiquo_client]
18
+
19
+ pconfig = @machine.provider_config
23
20
 
24
- @logger.info "Checking vApp '#{pconfig.virtualappliance}'"
21
+ @logger.info "Checking vApp '#{pconfig.virtualappliance}'"
25
22
 
26
- @logger.info "Looking up VDC '#{pconfig.virtualdatacenter}'"
27
- vdc = get_vdc(pconfig.virtualdatacenter)
28
- raise Abiquo::Errors::VDCNotFound, vdc: pconfig.virtualdatacenter if vdc.nil?
23
+ @logger.info "Looking up VDC '#{pconfig.virtualdatacenter}'"
24
+ vdc = get_vdc(client, pconfig.virtualdatacenter)
25
+ raise Abiquo::Errors::VDCNotFound, vdc: pconfig.virtualdatacenter if vdc.nil?
29
26
 
30
- vapp = get_vapp(vdc, pconfig.virtualappliance)
31
- unless vapp.nil? || vapp.link(:virtualmachines).get.count > 0
32
- @logger.info "vApp '#{pconfig.virtualappliance}' is empty, deleting."
33
- vapp.delete
27
+ vapp = get_vapp(vdc, pconfig.virtualappliance)
28
+ unless vapp.nil? || vapp.link(:virtualmachines).get.count > 0
29
+ @logger.info "vApp '#{pconfig.virtualappliance}' is empty, deleting."
30
+ vapp.delete
31
+ end
34
32
  end
35
33
 
36
34
  @app.call(env)
@@ -1,35 +1,33 @@
1
- require 'vagrant_abiquo/helpers/client'
2
1
  require 'vagrant_abiquo/helpers/abiquo'
3
2
 
4
3
  module VagrantPlugins
5
4
  module Abiquo
6
5
  module Actions
7
6
  class Deploy
8
- include Helpers::Client
9
7
  include Helpers::Abiquo
10
8
  include Vagrant::Util::Retryable
11
9
 
12
10
  def initialize(app, env)
13
11
  @app = app
14
12
  @machine = env[:machine]
15
- @client = client
16
13
  @env = env
17
14
  @logger = Log4r::Logger.new('vagrant::abiquo::deploy')
18
15
  end
19
16
 
20
17
  def call(env)
21
- vm = get_vm(@machine.id)
18
+ client = env[:abiquo_client]
19
+ vm = get_vm(client, @machine.id)
22
20
 
23
21
  # Deploying VM
24
22
  env[:ui].info I18n.t('vagrant_abiquo.info.deploy')
25
- task = deploy(vm)
23
+ task = deploy(client, vm)
26
24
 
27
25
  if task.state == 'FINISHED_SUCCESSFULLY'
28
26
  # Deploy successfully completed
29
27
  env[:ui].info I18n.t('vagrant_abiquo.info.deploycompleted')
30
28
 
31
- # Give time to the OS to boot.
32
- retryable(:tries => 20, :sleep => 5) do
29
+ # wait for ssh to be ready
30
+ retryable(:tries => 120, :sleep => 10) do
33
31
  next if env[:interrupted]
34
32
  raise 'not ready' if !@machine.communicate.ready?
35
33
  end
@@ -62,7 +60,7 @@ module VagrantPlugins
62
60
  destroy_env.delete(:interrupted)
63
61
  destroy_env[:config_validate] = false
64
62
  destroy_env[:force_confirm_destroy] = true
65
- env[:action_runner].run(Actions.destroy, destroy_env)
63
+ env[:action_runner].run(Actions.action_destroy, destroy_env)
66
64
  end
67
65
  end
68
66
  end
@@ -1,24 +1,22 @@
1
- require 'vagrant_abiquo/helpers/client'
2
1
  require 'vagrant_abiquo/helpers/abiquo'
3
2
 
4
3
  module VagrantPlugins
5
4
  module Abiquo
6
5
  module Actions
7
6
  class Destroy
8
- include Helpers::Client
9
7
  include Helpers::Abiquo
10
8
  include Vagrant::Util::Retryable
11
9
 
12
10
  def initialize(app, env)
13
11
  @app = app
14
12
  @machine = env[:machine]
15
- @client = client
16
13
  @logger = Log4r::Logger.new('vagrant::abiquo::destroy')
17
14
  end
18
15
 
19
16
  def call(env)
17
+ client = env[:abiquo_client]
20
18
  env[:ui].info I18n.t('vagrant_abiquo.info.destroying', vm: @machine.name)
21
- vm = get_vm(@machine.id)
19
+ vm = get_vm(client, @machine.id)
22
20
  vm.delete
23
21
 
24
22
  # Check when task finishes. This may take a while
@@ -1,24 +1,20 @@
1
- require 'vagrant_abiquo/helpers/client'
2
1
  require 'vagrant_abiquo/helpers/abiquo'
3
2
 
4
3
  module VagrantPlugins
5
4
  module Abiquo
6
5
  module Actions
7
6
  class PowerOff
8
- include Helpers::Client
9
7
  include Helpers::Abiquo
10
- include Vagrant::Util::Retryable
11
8
 
12
9
  def initialize(app, env)
13
10
  @app = app
14
11
  @machine = env[:machine]
15
- @client = AbiquoAPI.new(@machine.provider_config.abiquo_connection_data)
16
12
  @logger = Log4r::Logger.new('vagrant::abiquo::power_off')
17
13
  end
18
14
 
19
15
  def call(env)
20
- vm = get_vm(@machine.id)
21
- vm = power_off(vm)
16
+ vm = get_vm(client, @machine.id)
17
+ vm = power_off(client, vm)
22
18
  raise PowerOffError, vm: vm.label, state: vm.state if vm.state != 'OFF'
23
19
 
24
20
  @app.call(env)
@@ -1,24 +1,20 @@
1
- require 'vagrant_abiquo/helpers/client'
2
1
  require 'vagrant_abiquo/helpers/abiquo'
3
2
 
4
3
  module VagrantPlugins
5
4
  module Abiquo
6
5
  module Actions
7
6
  class PowerOn
8
- include Helpers::Client
9
7
  include Helpers::Abiquo
10
- include Vagrant::Util::Retryable
11
8
 
12
9
  def initialize(app, env)
13
10
  @app = app
14
11
  @machine = env[:machine]
15
- @client = AbiquoAPI.new(@machine.provider_config.abiquo_connection_data)
16
- @logger = Log4r::Logger.new('vagrant::abiquo::power_off')
12
+ @logger = Log4r::Logger.new('vagrant::abiquo::power_on')
17
13
  end
18
14
 
19
15
  def call(env)
20
- vm = get_vm(@machine.id)
21
- vm = poweron(vm)
16
+ vm = get_vm(client, @machine.id)
17
+ vm = poweron(client, vm)
22
18
  raise PowerOnError, vm: vm.label, state: vm.state if vm.state != 'ON'
23
19
 
24
20
  @app.call(env)
@@ -0,0 +1,41 @@
1
+ require 'vagrant_abiquo/helpers/abiquo'
2
+
3
+ module VagrantPlugins
4
+ module Abiquo
5
+ module Actions
6
+ class ReadSSHInfo
7
+ include Helpers::Abiquo
8
+
9
+ def initialize(app, env)
10
+ @app = app
11
+ @machine = env[:machine]
12
+ @logger = Log4r::Logger.new('vagrant::abiquo::ssh_info')
13
+ end
14
+
15
+ def call(env)
16
+ vm = get_vm(env[:abiquo_client], @machine.id)
17
+
18
+ return nil if vm.nil? || vm.state != 'ON'
19
+
20
+ ip ||= vm.link(:nics).get.first.ip
21
+
22
+ if @machine.config.ssh.username.nil?
23
+ template = vm.link(:virtualmachinetemplate).get
24
+ username = template.loginUser.nil? ? 'root' : template.loginUser
25
+ else
26
+ username = @machine.config.ssh.username
27
+ end
28
+
29
+ env[:machine_ssh_info] = {
30
+ :host => ip,
31
+ :port => 22,
32
+ :username => username
33
+ }
34
+
35
+ @app.call(env)
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end
41
+
@@ -1,25 +1,22 @@
1
- require 'vagrant_abiquo/helpers/client'
2
1
  require 'vagrant_abiquo/helpers/abiquo'
3
2
 
4
3
  module VagrantPlugins
5
4
  module Abiquo
6
5
  module Actions
7
6
  class Reset
8
- include Helpers::Client
9
7
  include Helpers::Abiquo
10
8
  include Vagrant::Util::Retryable
11
9
 
12
10
  def initialize(app, env)
13
11
  @app = app
14
12
  @machine = env[:machine]
15
- @client = AbiquoAPI.new(@machine.provider_config.abiquo_connection_data)
16
13
  @logger = Log4r::Logger.new('vagrant::abiquo::reset')
17
14
  end
18
15
 
19
16
  def call(env)
20
17
  env[:ui].info I18n.t('vagrant_abiquo.info.reloading')
21
- vm = get_vm(@machine.id)
22
- vm = reset(vm)
18
+ vm = get_vm(client, @machine.id)
19
+ vm = reset(client, vm)
23
20
 
24
21
  # Give time to the OS to boot.
25
22
  retryable(:tries => 120, :sleep => 10) do
@@ -43,7 +43,7 @@ module VagrantPlugins
43
43
 
44
44
  if @user_data == UNSET_VALUE
45
45
  # We will make sure the SSH key is injected.
46
- @user_data = '#!/bin/bash\necho "vagrant_abiquo :: making sure SSH key gets injected."'
46
+ @user_data = "#!/bin/bash\necho \"vagrant_abiquo :: making sure SSH key gets injected.\""
47
47
  end
48
48
  end
49
49
 
@@ -5,6 +5,10 @@ module VagrantPlugins
5
5
  error_namespace("vagrant_abiquo.errors")
6
6
  end
7
7
 
8
+ class InvalidStateError < AbiquoError
9
+ error_key(:invalid_state)
10
+ end
11
+
8
12
  class VDCNotFound < AbiquoError
9
13
  error_key(:vdc_not_found)
10
14
  end
@@ -1,27 +1,21 @@
1
1
  require 'abiquo-api'
2
- require 'log4r'
3
- include Log4r
4
2
 
5
3
  module VagrantPlugins
6
4
  module Abiquo
7
5
  module Helpers
8
6
  module Abiquo
9
- include Helpers::Client
10
-
11
- @logger = Log4r::Logger.new('vagrant::abiquo::helper')
12
-
13
7
  def vapp_name(machine)
14
8
  machine.provider_config.virtualappliance.nil? ? File.basename(machine.env.cwd) : machine.provider_config.virtualappliance
15
9
  end
16
10
 
17
- def get_vm(vm_url)
11
+ def get_vm(client, vm_url)
18
12
  vm_lnk = AbiquoAPI::Link.new :href => vm_url,
19
13
  :type => 'application/vnd.abiquo.virtualmachine+json',
20
14
  :client => client
21
15
  vm_lnk.get
22
16
  end
23
17
 
24
- def get_vdc(vdc_name)
18
+ def get_vdc(client, vdc_name)
25
19
  vdcs_lnk = AbiquoAPI::Link.new :href => 'cloud/virtualdatacenters',
26
20
  :type => "application/vnd.abiquo.virtualdatacenters+json",
27
21
  :client => client
@@ -32,7 +26,7 @@ module VagrantPlugins
32
26
  vdc.link(:virtualappliances).get.select {|va| va.name == name }.first
33
27
  end
34
28
 
35
- def create_vapp(vdc, name)
29
+ def create_vapp(client, vdc, name)
36
30
  vapp_hash = { 'name' => name }
37
31
  client.post(vdc.link(:virtualappliances), vapp_hash.to_json,
38
32
  accept: 'application/vnd.abiquo.virtualappliance+json',
@@ -48,18 +42,19 @@ module VagrantPlugins
48
42
 
49
43
  networks = []
50
44
  %w(privatenetworks network externalnetworks).each do |nettype|
51
- vdc.link(nettype.to_sym).get.each {|n| networks << n} if vdc.link? nettype.to_sym
45
+ next if vdc.link(:location).type.include? "publiccloudregion" and nettype == "network"
46
+ vdc.link(nettype.to_sym).get.each {|n| networks << n} if vdc.has_link? nettype.to_sym
52
47
  end
53
48
  networks.select {|n| n.name == net_name }.first
54
49
  end
55
50
 
56
- def create_vm(vm_def, vapp)
51
+ def create_vm(client, vm_def, vapp)
57
52
  client.post(vapp.link(:virtualmachines), vm_def.to_json,
58
53
  :content => "application/vnd.abiquo.virtualmachine+json",
59
54
  :accept => "application/vnd.abiquo.virtualmachine+json" )
60
55
  end
61
56
 
62
- def attach_net(vm, net_data)
57
+ def attach_net(client, vm, net_data)
63
58
  net_data.each do |net, ip|
64
59
  network = get_network(vm, net)
65
60
  return nil if network.nil?
@@ -97,7 +92,7 @@ module VagrantPlugins
97
92
  end
98
93
  end
99
94
 
100
- def deploy(vm)
95
+ def deploy(client, vm)
101
96
  task_lnk = client.post(vm.link(:deploy), '').link(:status).href
102
97
  task = AbiquoAPI::Link.new(:href => task_lnk,
103
98
  :type => 'application/vnd.abiquo.task+json',
@@ -112,7 +107,7 @@ module VagrantPlugins
112
107
  task
113
108
  end
114
109
 
115
- def apply_state(vm, state)
110
+ def apply_state(client, vm, state)
116
111
  task_lnk = client.put(vm.link(:state), {"state" => state}.to_json,
117
112
  :accept => 'application/vnd.abiquo.acceptedrequest+json',
118
113
  :content => 'application/vnd.abiquo.virtualmachinestate+json').link(:status)
@@ -126,15 +121,15 @@ module VagrantPlugins
126
121
  vm.link(:edit).get
127
122
  end
128
123
 
129
- def poweroff(vm)
130
- apply_state('OFF')
124
+ def poweroff(client, vm)
125
+ apply_state(client, 'OFF')
131
126
  end
132
127
 
133
- def poweron(vm)
134
- apply_state('ON')
128
+ def poweron(client, vm)
129
+ apply_state(client, 'ON')
135
130
  end
136
131
 
137
- def reset(vm)
132
+ def reset(client, vm)
138
133
  task = client.post(vm.link(:reset), '',
139
134
  :accept => 'application/vnd.abiquo.acceptedrequest+json',
140
135
  :content => 'application/json').link(:status).get
@@ -147,7 +142,7 @@ module VagrantPlugins
147
142
  vm.link(:edit).get
148
143
  end
149
144
 
150
- def update(vm)
145
+ def update(client, vm)
151
146
  task = client.put(vm.link(:edit), vm.to_json,
152
147
  :accept => 'application/vnd.abiquo.acceptedrequest+json',
153
148
  :content => vm.link(:edit).type)
@@ -13,19 +13,26 @@ module VagrantPlugins
13
13
  end
14
14
 
15
15
  provider(:abiquo, parallel: true) do
16
+ setup_i18n
17
+
16
18
  require_relative 'provider'
17
19
  Provider
18
20
  end
19
21
 
20
- action_hook(:create_vapp, :environment_load) do |hook|
21
- require_relative 'actions/create_vapp.rb'
22
- hook.prepend(Actions::CreatevApp)
22
+ def self.setup_i18n
23
+ I18n.load_path << File.expand_path('locales/en.yml', Abiquo.source_root)
24
+ I18n.reload!
23
25
  end
24
26
 
25
- action_hook(:delete_vapp, :environment_unload) do |hook|
26
- require_relative 'actions/delete_vapp.rb'
27
- hook.prepend(Actions::DeletevApp)
28
- end
27
+ # action_hook(:create_vapp, :environment_load) do |hook|
28
+ # require_relative 'actions/create_vapp.rb'
29
+ # hook.prepend(Actions::CreatevApp)
30
+ # end
31
+
32
+ # action_hook(:delete_vapp, :environment_unload) do |hook|
33
+ # require_relative 'actions/delete_vapp.rb'
34
+ # hook.prepend(Actions::DeletevApp)
35
+ # end
29
36
  end
30
37
  end
31
38
  end
@@ -1,66 +1,25 @@
1
- require 'vagrant_abiquo/helpers/client'
2
1
  require 'abiquo-api'
3
2
 
4
3
  module VagrantPlugins
5
4
  module Abiquo
6
5
  class Provider < Vagrant.plugin('2', :provider)
7
-
8
- def self.virtualmachine(machine, opts = {})
9
- @client ||= AbiquoAPI.new(machine.provider_config.abiquo_connection_data)
10
-
11
- vapp_name = machine.provider_config.virtualappliance.nil? ? File.basename(machine.env.cwd) : machine.provider_config.virtualappliance
12
- # If machine ID is nil try to lookup by name
13
- if machine.id.nil?
14
- vms_lnk = AbiquoAPI::Link.new :href => 'cloud/virtualmachines',
15
- :type => 'application/vnd.abiquo.virtualmachines+json',
16
- :client => @client
17
- @vm = vms_lnk.get.select {|v| v.label == machine.name.to_s and
18
- v.link(:virtualappliance).title == vapp_name }.first
19
- machine.id = @vm.url unless @vm.nil?
20
- @vm
21
- else
22
- # ID is the URL of the VM
23
- begin
24
- vm_lnk = AbiquoAPI::Link.new :href => machine.id,
25
- :type => 'application/vnd.abiquo.virtualmachine+json',
26
- :client => @client
27
- @vm = vm_lnk.get
28
- rescue AbiquoAPIClient::NotFound
29
- nil
30
- end
31
- end
32
- end
33
-
34
6
  def initialize(machine)
35
7
  @machine = machine
36
8
  end
37
9
 
38
10
  def action(name)
39
- return Actions.send(name) if Actions.respond_to?(name)
11
+ return Actions.send("action_#{name}") if Actions.respond_to?("action_#{name}")
40
12
  nil
41
13
  end
42
14
 
43
15
  def ssh_info
44
- return nil if state.id != :ON
45
- begin
46
- @ip ||= @vm.link(:nics).get.first.ip
47
- rescue AbiquoAPIClient::NotFound
48
- return nil
49
- end
50
-
51
- template = @vm.link(:virtualmachinetemplate).get unless @username
52
- @username = template.loginUser if template.respond_to? :loginUser
53
-
54
- {
55
- :host => @ip,
56
- :port => 22,
57
- :username => @username
58
- }
16
+ env = @machine.action("read_ssh_info")
17
+ env[:machine_ssh_info]
59
18
  end
60
19
 
61
20
  def state
62
- @vm = Provider.virtualmachine(@machine)
63
- state = @vm.nil? ? :not_created : @vm.state.to_sym
21
+ env = @machine.action('check_state')
22
+ state = env[:machine_state]
64
23
  long = short = state.to_s
65
24
  Vagrant::MachineState.new(state, short, long)
66
25
  end
@@ -1,5 +1,5 @@
1
1
  module VagrantPlugins
2
2
  module Abiquo
3
- VERSION = '0.0.8'
3
+ VERSION = '0.1.0'
4
4
  end
5
5
  end
data/locales/en.yml CHANGED
@@ -31,6 +31,7 @@ en:
31
31
  template: Abiquo template not found in config!
32
32
  cpuhwprofile: Either hardware profile or cpu core count is required!
33
33
  errors:
34
+ invalid_state: Operation cannot be performed. VM '%{vm}' is currently in state '%{state}'.
34
35
  vdc_not_found: Virtual datacenter '%{vdc}' not found
35
36
  template_not_found: Template %{template} not found in VDC '%{vdc}'
36
37
  poweroff: Error powering off VM %{vm}. Current state is %{state}
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: vagrant_abiquo
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.8
4
+ version: 0.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Daniel Beneyto
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2017-08-14 00:00:00.000000000 Z
12
+ date: 2017-08-18 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: abiquo-api
@@ -62,6 +62,7 @@ files:
62
62
  - lib/vagrant_abiquo.rb
63
63
  - lib/vagrant_abiquo/actions.rb
64
64
  - lib/vagrant_abiquo/actions/check_state.rb
65
+ - lib/vagrant_abiquo/actions/connect.rb
65
66
  - lib/vagrant_abiquo/actions/create.rb
66
67
  - lib/vagrant_abiquo/actions/create_vapp.rb
67
68
  - lib/vagrant_abiquo/actions/delete_vapp.rb
@@ -69,12 +70,11 @@ files:
69
70
  - lib/vagrant_abiquo/actions/destroy.rb
70
71
  - lib/vagrant_abiquo/actions/power_off.rb
71
72
  - lib/vagrant_abiquo/actions/power_on.rb
73
+ - lib/vagrant_abiquo/actions/read_ssh_info.rb
72
74
  - lib/vagrant_abiquo/actions/reset.rb
73
75
  - lib/vagrant_abiquo/config.rb
74
76
  - lib/vagrant_abiquo/errors.rb
75
77
  - lib/vagrant_abiquo/helpers/abiquo.rb
76
- - lib/vagrant_abiquo/helpers/client.rb
77
- - lib/vagrant_abiquo/helpers/result.rb
78
78
  - lib/vagrant_abiquo/plugin.rb
79
79
  - lib/vagrant_abiquo/provider.rb
80
80
  - lib/vagrant_abiquo/version.rb
@@ -1,15 +0,0 @@
1
- require 'abiquo-api'
2
- require 'log4r'
3
- include Log4r
4
-
5
- module VagrantPlugins
6
- module Abiquo
7
- module Helpers
8
- module Client
9
- def client
10
- @client ||= AbiquoAPI.new(@machine.provider_config.abiquo_connection_data)
11
- end
12
- end
13
- end
14
- end
15
- end
@@ -1,40 +0,0 @@
1
- module VagrantPlugins
2
- module Abiquo
3
- module Helpers
4
- class Result
5
- def initialize(body)
6
- @result = body
7
- end
8
-
9
- def [](key)
10
- @result[key.to_s]
11
- end
12
-
13
- def find_id(sub_obj, search)
14
- find(sub_obj, search)["id"]
15
- end
16
-
17
- def find(sub_obj, search)
18
- key = search.keys.first
19
- value = search[key].to_s
20
- key = key.to_s
21
-
22
- result = @result[sub_obj.to_s].inject(nil) do |result, obj|
23
- obj[key] == value ? obj : result
24
- end
25
-
26
- result || error(sub_obj, key, value)
27
- end
28
-
29
- def error(sub_obj, key, value)
30
- raise(Errors::ResultMatchError, {
31
- :key => key,
32
- :value => value,
33
- :collection_name => sub_obj.to_s,
34
- :sub_obj => @result[sub_obj.to_s]
35
- })
36
- end
37
- end
38
- end
39
- end
40
- end