smartdc 0.3.0 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (64) hide show
  1. data/Gemfile +7 -7
  2. data/README.md +5 -5
  3. data/VERSION +1 -1
  4. data/bin/sdc-addmachinemetadata +2 -2
  5. data/bin/sdc-addmachinetag +2 -2
  6. data/bin/sdc-createinstrumentation +1 -2
  7. data/bin/sdc-createkey +1 -2
  8. data/bin/sdc-createmachine +5 -5
  9. data/bin/sdc-createmachinesnapshot +1 -2
  10. data/bin/sdc-deleteinstrumentation +4 -2
  11. data/bin/sdc-deletekey +4 -2
  12. data/bin/sdc-deletemachine +4 -2
  13. data/bin/sdc-deletemachinemetadata +4 -2
  14. data/bin/sdc-deletemachinesnapshot +4 -3
  15. data/bin/sdc-deletemachinetag +4 -2
  16. data/bin/sdc-describeanalytics +1 -2
  17. data/bin/sdc-getdatacenter +1 -2
  18. data/bin/sdc-getdataset +1 -2
  19. data/bin/sdc-getinstrumentation +1 -2
  20. data/bin/sdc-getkey +1 -2
  21. data/bin/sdc-getmachine +3 -2
  22. data/bin/sdc-getmachinemetadata +4 -3
  23. data/bin/sdc-getmachinesnapshot +1 -2
  24. data/bin/sdc-getmachinetag +1 -2
  25. data/bin/sdc-getpackage +1 -2
  26. data/bin/sdc-listdatacenters +1 -2
  27. data/bin/sdc-listdatasets +1 -2
  28. data/bin/sdc-listinstrumentations +1 -2
  29. data/bin/sdc-listkeys +1 -2
  30. data/bin/sdc-listmachines +1 -2
  31. data/bin/sdc-listmachinesnapshots +1 -2
  32. data/bin/sdc-listmachinetags +1 -2
  33. data/bin/sdc-listpackages +1 -2
  34. data/bin/sdc-rebootmachine +4 -2
  35. data/bin/sdc-resizemachine +5 -3
  36. data/bin/sdc-setup +7 -3
  37. data/bin/sdc-startmachine +4 -2
  38. data/bin/sdc-startmachinefromsnapshot +4 -3
  39. data/bin/sdc-stopmachine +4 -2
  40. data/lib/smartdc.rb +1 -0
  41. data/lib/smartdc/api/analytics/instrumentations.rb +1 -2
  42. data/lib/smartdc/api/keys.rb +0 -1
  43. data/lib/smartdc/api/machine/metadata.rb +1 -2
  44. data/lib/smartdc/api/machine/snapshots.rb +1 -3
  45. data/lib/smartdc/api/machine/tags.rb +1 -2
  46. data/lib/smartdc/api/machines.rb +0 -5
  47. data/lib/smartdc/client.rb +4 -0
  48. data/lib/smartdc/error.rb +35 -0
  49. data/lib/smartdc/request.rb +13 -10
  50. data/lib/smartdc/response/mashify.rb +29 -0
  51. data/lib/smartdc/response/parse_json.rb +26 -0
  52. data/lib/smartdc/response/raise_error.rb +38 -0
  53. data/smartdc.gemspec +25 -23
  54. data/spec/smartdc/api/analytics_spec.rb +1 -1
  55. data/spec/smartdc/api/keys_spec.rb +1 -1
  56. data/spec/smartdc/api/machine/metadata_spec.rb +21 -4
  57. data/spec/smartdc/api/machine/snapshots_spec.rb +17 -5
  58. data/spec/smartdc/api/machine/tags_spec.rb +21 -4
  59. data/spec/smartdc/api/machines_spec.rb +19 -23
  60. data/spec/smartdc/request_spec.rb +3 -2
  61. data/spec/spec_helper.rb +7 -1
  62. metadata +33 -31
  63. data/lib/faraday/response/mashify.rb +0 -26
  64. data/lib/faraday/response/parse_json.rb +0 -22
@@ -35,29 +35,33 @@ if config[:password].size == 0
35
35
  exit 1
36
36
  end
37
37
 
38
+ config[:format] = 'json'
39
+
38
40
  Pathname.new(File.dirname(CONFIG)).mkpath unless File.exist?(File.dirname(CONFIG))
39
41
  File.open(CONFIG, 'w') do |file|
40
42
  file.write MultiJson.encode(config)
41
43
  end
42
44
 
43
45
  begin
46
+ client.format = 'mash'
44
47
  datacenters = client.datacenters.find
45
48
  if client.datacenters.find.first[1] == config[:url]
46
49
  puts 'Successful configuration.'
47
50
 
51
+ client.format = 'json'
48
52
  Pathname.new(File.dirname(DATASETS)).mkpath unless File.exist?(File.dirname(DATASETS))
49
53
  File.open(DATASETS, 'w') do |file|
50
- file.write MultiJson.encode(client.datasets.find)
54
+ file.write client.datasets.find
51
55
  end
52
56
 
53
57
  Pathname.new(File.dirname(PACKAGES)).mkpath unless File.exist?(File.dirname(PACKAGES))
54
58
  File.open(PACKAGES, 'w') do |file|
55
- file.write MultiJson.encode(client.packages.find)
59
+ file.write client.packages.find
56
60
  end
57
61
  else
58
62
  puts 'Failed Configuration.'
59
63
  end
60
64
  rescue => e
61
- puts e
65
+ puts e.inspect
62
66
  puts 'Failed Setup.'
63
67
  end
@@ -4,7 +4,9 @@ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
4
4
  require 'cli_helper'
5
5
 
6
6
  begin
7
- pp client.machines(ARGV[0]).start
7
+ client.machines(ARGV[0]).start
8
8
  rescue => e
9
- puts e
9
+ puts e.inspect
10
+ else
11
+ puts "Success"
10
12
  end
@@ -21,8 +21,9 @@ OptionParser.new do |opts|
21
21
  end
22
22
 
23
23
  begin
24
- client.request.return_variable = 'json'
25
- puts client.machines(ARGV[0]).snapshots(options[:name]).start
24
+ client.machines(ARGV[0]).snapshots(options[:name]).start
26
25
  rescue => e
27
- puts e
26
+ puts e.inspect
27
+ else
28
+ puts "Success"
28
29
  end
@@ -4,7 +4,9 @@ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
4
4
  require 'cli_helper'
5
5
 
6
6
  begin
7
- pp client.machines(ARGV[0]).stop
7
+ client.machines(ARGV[0]).stop
8
8
  rescue => e
9
- puts e
9
+ puts e.inspect
10
+ else
11
+ puts "Success"
10
12
  end
@@ -1,5 +1,6 @@
1
1
  require 'smartdc/client'
2
2
  require 'smartdc/request'
3
+ require 'smartdc/error'
3
4
 
4
5
  module Smartdc
5
6
  def self.new(options={})
@@ -18,12 +18,11 @@ module Smartdc::Api
18
18
  end
19
19
 
20
20
  def find(params={})
21
- request.get('my/analytics/instrumentations/', params)
21
+ request.get('my/analytics/instrumentations', params)
22
22
  end
23
23
 
24
24
  def delete
25
25
  request.delete('my/analytics/instrumentations/' + id.to_s)
26
- request.response.status == 204 ? true : false
27
26
  end
28
27
 
29
28
  def value
@@ -24,7 +24,6 @@ module Smartdc
24
24
  def delete
25
25
  raise ArgumentError unless id
26
26
  request.delete('my/keys/' + id.to_s)
27
- request.response.status == 204 ? true : false
28
27
  end
29
28
  end
30
29
  end
@@ -19,12 +19,11 @@ module Smartdc::Api
19
19
  end
20
20
 
21
21
  def find(params={})
22
- request.get('my/machines/' + @id1.to_s + '/metadata/', params)
22
+ request.get('my/machines/' + @id1.to_s + '/metadata', params)
23
23
  end
24
24
 
25
25
  def delete
26
26
  request.delete('my/machines/' + @id1.to_s + '/metadata/' + id.to_s)
27
- request.response.status == 204 ? true : false
28
27
  end
29
28
  end
30
29
  end
@@ -16,7 +16,6 @@ module Smartdc::Api
16
16
  def start
17
17
  raise ArgumentError unless id
18
18
  request.post('my/machines/' + @id1.to_s + '/snapshots/' + id.to_s)
19
- request.response.status == 202 ? true : false
20
19
  end
21
20
 
22
21
  def read
@@ -25,12 +24,11 @@ module Smartdc::Api
25
24
  end
26
25
 
27
26
  def find(params={})
28
- request.get('my/machines/' + @id1.to_s + '/snapshots/', params)
27
+ request.get('my/machines/' + @id1.to_s + '/snapshots', params)
29
28
  end
30
29
 
31
30
  def delete
32
31
  request.delete('my/machines/' + @id1.to_s + '/snapshots/' + id.to_s)
33
- request.response.status == 204 ? true : false
34
32
  end
35
33
  end
36
34
  end
@@ -19,12 +19,11 @@ module Smartdc::Api
19
19
  end
20
20
 
21
21
  def find(params={})
22
- request.get('my/machines/' + @id1.to_s + '/tags/', params)
22
+ request.get('my/machines/' + @id1.to_s + '/tags', params)
23
23
  end
24
24
 
25
25
  def delete
26
26
  request.delete('my/machines/' + @id1.to_s + '/tags/' + id.to_s)
27
- request.response.status == 204 ? true : false
28
27
  end
29
28
  end
30
29
  end
@@ -28,32 +28,27 @@ module Smartdc
28
28
  def delete
29
29
  raise ArgumentError unless id
30
30
  request.delete('my/machines/' + id.to_s)
31
- request.response.status == 204 ? true : false
32
31
  end
33
32
 
34
33
  def stop
35
34
  raise ArgumentError unless id
36
35
  request.post('my/machines/' + id.to_s, {'action'=>'stop'})
37
- request.response.status == 202 ? true : false
38
36
  end
39
37
 
40
38
  def start
41
39
  raise ArgumentError unless id
42
40
  request.post('my/machines/' + id.to_s, {'action'=>'start'})
43
- request.response.status == 202 ? true : false
44
41
  end
45
42
 
46
43
  def reboot
47
44
  raise ArgumentError unless id
48
45
  request.post('my/machines/' + id.to_s, {'action'=>'reboot'})
49
- request.response.status == 202 ? true : false
50
46
  end
51
47
 
52
48
  def resize(params={})
53
49
  raise ArgumentError unless id
54
50
  params[:action] = 'resize'
55
51
  request.post('my/machines/' + id.to_s, params)
56
- request.response.status == 202 ? true : false
57
52
  end
58
53
 
59
54
  def tags(_id=nil)
@@ -13,6 +13,10 @@ module Smartdc
13
13
  @request ||= Smartdc::Request.new(options)
14
14
  end
15
15
 
16
+ def format=(format)
17
+ @request.format = format
18
+ end
19
+
16
20
  def keys(id=nil)
17
21
  Smartdc::Api::Keys.new(request, id)
18
22
  end
@@ -0,0 +1,35 @@
1
+ module Smartdc
2
+ class Error < StandardError
3
+ attr_reader :response
4
+
5
+ def initialize(response)
6
+ @response = response
7
+ begin
8
+ body = JSON.parse(response[:body])
9
+ if body['error_message']
10
+ super(body['error_message'])
11
+ else
12
+ super(response[:body])
13
+ end
14
+ rescue
15
+ super(response[:body])
16
+ end
17
+ end
18
+
19
+ def response_status
20
+ response[:status]
21
+ end
22
+ end
23
+
24
+ class Error::BadRequest < Smartdc::Error; end
25
+ class Error::Unauthorized < Smartdc::Error; end
26
+ class Error::Forbidden < Smartdc::Error; end
27
+ class Error::NotFound < Smartdc::Error; end
28
+ class Error::MethodNotAllowed < Smartdc::Error; end
29
+ class Error::NotAcceptable < Smartdc::Error; end
30
+ class Error::Conflict < Smartdc::Error; end
31
+ class Error::InternalServerError < Smartdc::Error; end
32
+ class Error::NotImplemented < Smartdc::Error; end
33
+ class Error::BadGateway < Smartdc::Error; end
34
+ class Error::ServiceUnavailable < Smartdc::Error; end
35
+ end
@@ -1,19 +1,21 @@
1
1
  require 'hashie/mash'
2
2
  require 'multi_json'
3
3
  require 'faraday'
4
- require 'faraday/response/mashify'
5
- require 'faraday/response/parse_json'
4
+ require 'smartdc/response/mashify'
5
+ require 'smartdc/response/parse_json'
6
+ require 'smartdc/response/raise_error'
6
7
 
7
8
  module Smartdc
8
9
  class Request
9
- attr_reader :url, :version, :response, :username, :password
10
- attr_accessor :return_variable
10
+ attr_reader :url, :version, :username, :password
11
+ attr_accessor :format
11
12
 
12
13
  def initialize(options)
13
14
  @url = options['url']
14
15
  @version = options['version']
15
16
  @username = options['username']
16
17
  @password = options['password']
18
+ @format = options['format']
17
19
  end
18
20
 
19
21
  def get(path, params={})
@@ -34,7 +36,7 @@ module Smartdc
34
36
 
35
37
  private
36
38
  def request(method, path, params={})
37
- @response = connection.send(method) do |request|
39
+ response = connection.send(method) do |request|
38
40
  case method
39
41
  when :get
40
42
  request.url path, params
@@ -46,11 +48,11 @@ module Smartdc
46
48
  request.headers = {'content-length'=>'0'}
47
49
  end
48
50
  end
49
- @response.body
51
+ response.body
50
52
  end
51
53
 
52
54
  def connection
53
- case return_variable
55
+ case format
54
56
  when 'mash', nil
55
57
  middleware = 3
56
58
  when 'hash'
@@ -72,14 +74,15 @@ module Smartdc
72
74
 
73
75
  Faraday.new(options) do |builder|
74
76
  builder.use Faraday::Request::JSON
75
- builder.use Faraday::Response::Mashify if middleware > 2
76
- builder.use Faraday::Response::ParseJson if middleware > 1
77
+ builder.use Smartdc::Response::Mashify if middleware > 2
78
+ builder.use Smartdc::Response::ParseJson if middleware > 1
79
+ builder.use Smartdc::Response::RaiseError
77
80
  builder.adapter Faraday.default_adapter
78
81
  end
79
82
  end
80
83
 
81
84
  def basic_auth(username, password)
82
- 'Basic ' + Base64.encode64("#{username}:#{password}").gsub!("\n", '')
85
+ 'Basic ' + ["#{username}:#{password}"].pack('m').delete("\r\n")
83
86
  end
84
87
  end
85
88
  end
@@ -0,0 +1,29 @@
1
+ require 'faraday'
2
+
3
+ module Smartdc
4
+ module Response
5
+ class Mashify < Faraday::Response::Middleware
6
+ class << self
7
+ attr_accessor :mash_class
8
+ end
9
+
10
+ dependency do
11
+ require 'hashie/mash'
12
+ self.mash_class = ::Hashie::Mash
13
+ end
14
+
15
+ def parse(body)
16
+ case body
17
+ when Hash
18
+ self.class.mash_class.new(body)
19
+ when Array
20
+ body.map { |item| item.is_a?(Hash) ? self.class.mash_class.new(item) : item }
21
+ else
22
+ body
23
+ end
24
+ rescue
25
+ body
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,26 @@
1
+ require 'faraday'
2
+
3
+ module Smartdc
4
+ module Response
5
+ class ParseJson < Faraday::Response::Middleware
6
+ dependency do
7
+ require 'multi_json'
8
+ end
9
+
10
+ def parse(body)
11
+ case body
12
+ when ''
13
+ nil
14
+ when 'true'
15
+ true
16
+ when 'false'
17
+ false
18
+ else
19
+ ::MultiJson.decode(body)
20
+ end
21
+ rescue
22
+ body
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,38 @@
1
+ require 'faraday'
2
+
3
+ module Smartdc
4
+ module Response
5
+ class RaiseError < Faraday::Response::Middleware
6
+ def on_complete(env)
7
+ case env[:status]
8
+ when 400
9
+ raise Smartdc::Error::BadRequest, response_values(env)
10
+ when 401
11
+ raise Smartdc::Error::Unauthorized, response_values(env)
12
+ when 403
13
+ raise Smartdc::Error::Forbidden, response_values(env)
14
+ when 404
15
+ raise Smartdc::Error::NotFound, response_values(env)
16
+ when 405
17
+ raise Smartdc::Error::MethodNotAllowed, response_values(env)
18
+ when 406
19
+ raise Smartdc::Error::NotAcceptable, response_values(env)
20
+ when 409
21
+ raise Smartdc::Error::Conflict, response_values(env)
22
+ when 500
23
+ raise Smartdc::Error::InternalServerError, response_values(env)
24
+ when 501
25
+ raise Smartdc::Error::NotImplemented, response_values(env)
26
+ when 502
27
+ raise Smartdc::Error::BadGateway, response_values(env)
28
+ when 503
29
+ raise Smartdc::Error::ServiceUnavailable, response_values(env)
30
+ end
31
+ end
32
+
33
+ def response_values(env)
34
+ {:status => env[:status], :headers => env[:response_headers], :body => env[:body]}
35
+ end
36
+ end
37
+ end
38
+ end
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = "smartdc"
8
- s.version = "0.3.0"
8
+ s.version = "0.4.0"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["ogom"]
12
- s.date = "2011-12-03"
12
+ s.date = "2012-03-08"
13
13
  s.description = "smartdc is SmartDataCenter Public API."
14
14
  s.email = "ogom@hotmail.co.jp"
15
15
  s.executables = ["sdc-addmachinemetadata", "sdc-addmachinetag", "sdc-createinstrumentation", "sdc-createkey", "sdc-createmachine", "sdc-createmachinesnapshot", "sdc-deleteinstrumentation", "sdc-deletekey", "sdc-deletemachine", "sdc-deletemachinemetadata", "sdc-deletemachinesnapshot", "sdc-deletemachinetag", "sdc-describeanalytics", "sdc-getdatacenter", "sdc-getdataset", "sdc-getinstrumentation", "sdc-getkey", "sdc-getmachine", "sdc-getmachinemetadata", "sdc-getmachinesnapshot", "sdc-getmachinetag", "sdc-getpackage", "sdc-listdatacenters", "sdc-listdatasets", "sdc-listinstrumentations", "sdc-listkeys", "sdc-listmachines", "sdc-listmachinesnapshots", "sdc-listmachinetags", "sdc-listpackages", "sdc-rebootmachine", "sdc-resizemachine", "sdc-setup", "sdc-startmachine", "sdc-startmachinefromsnapshot", "sdc-stopmachine"]
@@ -63,8 +63,6 @@ Gem::Specification.new do |s|
63
63
  "config/fixtures/key.json",
64
64
  "config/fixtures/tag.json",
65
65
  "lib/cli_helper.rb",
66
- "lib/faraday/response/mashify.rb",
67
- "lib/faraday/response/parse_json.rb",
68
66
  "lib/smartdc.rb",
69
67
  "lib/smartdc/api/analytics.rb",
70
68
  "lib/smartdc/api/analytics/instrumentations.rb",
@@ -77,7 +75,11 @@ Gem::Specification.new do |s|
77
75
  "lib/smartdc/api/machines.rb",
78
76
  "lib/smartdc/api/packages.rb",
79
77
  "lib/smartdc/client.rb",
78
+ "lib/smartdc/error.rb",
80
79
  "lib/smartdc/request.rb",
80
+ "lib/smartdc/response/mashify.rb",
81
+ "lib/smartdc/response/parse_json.rb",
82
+ "lib/smartdc/response/raise_error.rb",
81
83
  "smartdc.gemspec",
82
84
  "spec/smartdc/api/analytics_spec.rb",
83
85
  "spec/smartdc/api/datacenters_spec.rb",
@@ -96,42 +98,42 @@ Gem::Specification.new do |s|
96
98
  s.homepage = "http://github.com/ogom/ruby-smartdc"
97
99
  s.licenses = ["MIT"]
98
100
  s.require_paths = ["lib"]
99
- s.rubygems_version = "1.8.10"
101
+ s.rubygems_version = "1.8.15"
100
102
  s.summary = "SmartDataCenter CloudApi client by ruby."
101
103
 
102
104
  if s.respond_to? :specification_version then
103
105
  s.specification_version = 3
104
106
 
105
107
  if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
106
- s.add_runtime_dependency(%q<faraday>, ["~> 0.7.5"])
108
+ s.add_runtime_dependency(%q<faraday>, ["~> 0.7.6"])
107
109
  s.add_runtime_dependency(%q<hashie>, ["~> 1.2.0"])
108
- s.add_runtime_dependency(%q<multi_json>, ["~> 1.0.3"])
109
- s.add_runtime_dependency(%q<multipart-post>, ["~> 1.1.3"])
110
- s.add_development_dependency(%q<rspec>, ["~> 2.7.0"])
110
+ s.add_runtime_dependency(%q<multi_json>, ["~> 1.1.0"])
111
+ s.add_runtime_dependency(%q<multipart-post>, ["~> 1.1.4"])
112
+ s.add_development_dependency(%q<rspec>, ["~> 2.8.0"])
111
113
  s.add_development_dependency(%q<bundler>, ["~> 1.0.0"])
112
- s.add_development_dependency(%q<jeweler>, ["~> 1.6.4"])
113
- s.add_development_dependency(%q<rcov>, [">= 0"])
114
+ s.add_development_dependency(%q<jeweler>, ["~> 1.8.3"])
115
+ s.add_development_dependency(%q<rcov>, ["~> 0.9.11"])
114
116
  s.add_development_dependency(%q<uuid>, ["~> 2.3.4"])
115
117
  else
116
- s.add_dependency(%q<faraday>, ["~> 0.7.5"])
118
+ s.add_dependency(%q<faraday>, ["~> 0.7.6"])
117
119
  s.add_dependency(%q<hashie>, ["~> 1.2.0"])
118
- s.add_dependency(%q<multi_json>, ["~> 1.0.3"])
119
- s.add_dependency(%q<multipart-post>, ["~> 1.1.3"])
120
- s.add_dependency(%q<rspec>, ["~> 2.7.0"])
120
+ s.add_dependency(%q<multi_json>, ["~> 1.1.0"])
121
+ s.add_dependency(%q<multipart-post>, ["~> 1.1.4"])
122
+ s.add_dependency(%q<rspec>, ["~> 2.8.0"])
121
123
  s.add_dependency(%q<bundler>, ["~> 1.0.0"])
122
- s.add_dependency(%q<jeweler>, ["~> 1.6.4"])
123
- s.add_dependency(%q<rcov>, [">= 0"])
124
+ s.add_dependency(%q<jeweler>, ["~> 1.8.3"])
125
+ s.add_dependency(%q<rcov>, ["~> 0.9.11"])
124
126
  s.add_dependency(%q<uuid>, ["~> 2.3.4"])
125
127
  end
126
128
  else
127
- s.add_dependency(%q<faraday>, ["~> 0.7.5"])
129
+ s.add_dependency(%q<faraday>, ["~> 0.7.6"])
128
130
  s.add_dependency(%q<hashie>, ["~> 1.2.0"])
129
- s.add_dependency(%q<multi_json>, ["~> 1.0.3"])
130
- s.add_dependency(%q<multipart-post>, ["~> 1.1.3"])
131
- s.add_dependency(%q<rspec>, ["~> 2.7.0"])
131
+ s.add_dependency(%q<multi_json>, ["~> 1.1.0"])
132
+ s.add_dependency(%q<multipart-post>, ["~> 1.1.4"])
133
+ s.add_dependency(%q<rspec>, ["~> 2.8.0"])
132
134
  s.add_dependency(%q<bundler>, ["~> 1.0.0"])
133
- s.add_dependency(%q<jeweler>, ["~> 1.6.4"])
134
- s.add_dependency(%q<rcov>, [">= 0"])
135
+ s.add_dependency(%q<jeweler>, ["~> 1.8.3"])
136
+ s.add_dependency(%q<rcov>, ["~> 0.9.11"])
135
137
  s.add_dependency(%q<uuid>, ["~> 2.3.4"])
136
138
  end
137
139
  end