bosh-director 1.5.0.pre.1269 → 1.5.0.pre.1274

Sign up to get free protection for your applications and to get access to all the features.
data/lib/bosh/director.rb CHANGED
@@ -55,7 +55,6 @@ require 'bosh/director/event_log'
55
55
  require 'bosh/director/task_result_file'
56
56
  require 'bosh/director/blob_util'
57
57
 
58
- require 'bosh/director/client'
59
58
  require 'bosh/director/agent_client'
60
59
  require 'cloud'
61
60
  require 'bosh/director/compile_task'
@@ -1,11 +1,12 @@
1
1
  require 'bosh/director/agent_message_converter'
2
2
 
3
3
  module Bosh::Director
4
- class AgentClient < Client
5
-
4
+ class AgentClient
6
5
  DEFAULT_POLL_INTERVAL = 1.0
7
6
 
8
- def initialize(id, options = {})
7
+ attr_accessor :id
8
+
9
+ def self.with_defaults(id, options = {})
9
10
  defaults = {
10
11
  retry_methods: { # in case of timeout errors
11
12
  get_state: 2,
@@ -14,32 +15,205 @@ module Bosh::Director
14
15
  }
15
16
 
16
17
  credentials = Bosh::Director::Models::Vm.find(:agent_id => id).credentials
17
- if credentials
18
- defaults.merge!(credentials: credentials)
19
- end
20
-
21
- super('agent', id, defaults.merge(options))
22
- end
23
-
24
- [
25
- :prepare,
26
- :apply,
27
- :compile_package,
28
- :drain,
29
- :fetch_logs,
30
- :migrate_disk,
31
- :mount_disk,
32
- :stop,
33
- :unmount_disk,
34
- ].each do |method|
35
- define_method (method) do |*args|
36
- task = AgentMessageConverter.convert_old_message_to_new(super(*args))
37
- while task['state'] == 'running'
38
- sleep(DEFAULT_POLL_INTERVAL)
39
- task = AgentMessageConverter.convert_old_message_to_new(get_task(task['agent_task_id']))
18
+ defaults.merge!(credentials: credentials) if credentials
19
+
20
+ self.new('agent', id, defaults.merge(options))
21
+ end
22
+
23
+ def initialize(service_name, client_id, options = {})
24
+ @service_name = service_name
25
+ @client_id = client_id
26
+ @nats_rpc = Config.nats_rpc
27
+ @timeout = options[:timeout] || 45
28
+ @logger = Config.logger
29
+ @retry_methods = options[:retry_methods] || {}
30
+
31
+ if options[:credentials]
32
+ @encryption_handler =
33
+ Bosh::Core::EncryptionHandler.new(@client_id, options[:credentials])
34
+ end
35
+
36
+ @resource_manager = Api::ResourceManager.new
37
+ end
38
+
39
+ def method_missing(method_name, *args)
40
+ send_message(method_name, *args)
41
+ end
42
+
43
+ def prepare(*args)
44
+ send_long_running_message(:prepare, *args)
45
+ end
46
+
47
+ def apply(*args)
48
+ send_long_running_message(:apply, *args)
49
+ end
50
+
51
+ def compile_package(*args)
52
+ send_long_running_message(:compile_package, *args)
53
+ end
54
+
55
+ def drain(*args)
56
+ send_long_running_message(:drain, *args)
57
+ end
58
+
59
+ def fetch_logs(*args)
60
+ send_long_running_message(:fetch_logs, *args)
61
+ end
62
+
63
+ def migrate_disk(*args)
64
+ send_long_running_message(:migrate_disk, *args)
65
+ end
66
+
67
+ def mount_disk(*args)
68
+ send_long_running_message(:mount_disk, *args)
69
+ end
70
+
71
+ def unmount_disk(*args)
72
+ send_long_running_message(:unmount_disk, *args)
73
+ end
74
+
75
+ def stop(*args)
76
+ send_long_running_message(:stop, *args)
77
+ end
78
+
79
+ def wait_until_ready(deadline = 600)
80
+ old_timeout = @timeout
81
+ @timeout = 1.0
82
+ @deadline = Time.now.to_i + deadline
83
+
84
+ begin
85
+ ping
86
+ rescue RpcTimeout
87
+ retry if @deadline - Time.now.to_i > 0
88
+ raise RpcTimeout, "Timed out pinging to #{@client_id} after #{deadline} seconds"
89
+ rescue RpcRemoteException => e
90
+ retry if e.message =~ /^restarting agent/ && @deadline - Time.now.to_i > 0
91
+ raise e
92
+ ensure
93
+ @timeout = old_timeout
94
+ end
95
+ end
96
+
97
+ def handle_method(method_name, args)
98
+ result = {}
99
+ result.extend(MonitorMixin)
100
+
101
+ cond = result.new_cond
102
+ timeout_time = Time.now.to_f + @timeout
103
+
104
+ request = { :method => method_name, :arguments => args }
105
+
106
+ if @encryption_handler
107
+ @logger.info("Request: #{request}")
108
+ request = { "encrypted_data" => @encryption_handler.encrypt(request) }
109
+ request["session_id"] = @encryption_handler.session_id
110
+ end
111
+
112
+ recipient = "#{@service_name}.#{@client_id}"
113
+
114
+ request_id = @nats_rpc.send_request(recipient, request) do |response|
115
+ if @encryption_handler
116
+ begin
117
+ response = @encryption_handler.decrypt(response["encrypted_data"])
118
+ rescue Bosh::Core::EncryptionHandler::CryptError => e
119
+ response["exception"] = "CryptError: #{e.inspect} #{e.backtrace}"
120
+ end
121
+ @logger.info("Response: #{response}")
122
+ end
123
+
124
+ result.synchronize do
125
+ inject_compile_log(response)
126
+ result.merge!(response)
127
+ cond.signal
128
+ end
129
+ end
130
+
131
+ result.synchronize do
132
+ while result.empty?
133
+ timeout = timeout_time - Time.now.to_f
134
+ unless timeout > 0
135
+ @nats_rpc.cancel_request(request_id)
136
+ raise RpcTimeout,
137
+ "Timed out sending `#{method_name}' to #{@client_id} " +
138
+ "after #{@timeout} seconds"
139
+ end
140
+ cond.wait(timeout)
141
+ end
142
+ end
143
+
144
+ if result.has_key?("exception")
145
+ raise RpcRemoteException, format_exception(result["exception"])
146
+ end
147
+
148
+ result["value"]
149
+ end
150
+
151
+ # Returns formatted exception information
152
+ # @param [Hash|#to_s] exception Serialized exception
153
+ # @return [String]
154
+ def format_exception(exception)
155
+ return exception.to_s unless exception.is_a?(Hash)
156
+
157
+ msg = exception["message"].to_s
158
+
159
+ if exception["backtrace"]
160
+ msg += "\n"
161
+ msg += Array(exception["backtrace"]).join("\n")
162
+ end
163
+
164
+ if exception["blobstore_id"]
165
+ blob = download_and_delete_blob(exception["blobstore_id"])
166
+ msg += "\n"
167
+ msg += blob.to_s
168
+ end
169
+
170
+ msg
171
+ end
172
+
173
+ private
174
+
175
+ # the blob is removed from the blobstore once we have fetched it,
176
+ # but if there is a crash before it is injected into the response
177
+ # and then logged, there is a chance that we lose it
178
+ def inject_compile_log(response)
179
+ if response["value"] && response["value"].is_a?(Hash) &&
180
+ response["value"]["result"].is_a?(Hash) &&
181
+ blob_id = response["value"]["result"]["compile_log_id"]
182
+ compile_log = download_and_delete_blob(blob_id)
183
+ response["value"]["result"]["compile_log"] = compile_log
184
+ end
185
+ end
186
+
187
+ # Downloads blob and ensures it's deleted from the blobstore
188
+ # @param [String] blob_id Blob id
189
+ # @return [String] Blob contents
190
+ def download_and_delete_blob(blob_id)
191
+ blob = @resource_manager.get_resource(blob_id)
192
+ blob
193
+ ensure
194
+ @resource_manager.delete_resource(blob_id)
195
+ end
196
+
197
+ def send_message(message_name, *args)
198
+ retries = @retry_methods[message_name] || 0
199
+ begin
200
+ handle_method(message_name, args)
201
+ rescue RpcTimeout
202
+ if retries > 0
203
+ retries -= 1
204
+ retry
40
205
  end
41
- task['value']
206
+ raise
207
+ end
208
+ end
209
+
210
+ def send_long_running_message(method_name, *args)
211
+ task = AgentMessageConverter.convert_old_message_to_new(send_message(method_name, *args))
212
+ while task['state'] == 'running'
213
+ sleep(DEFAULT_POLL_INTERVAL)
214
+ task = AgentMessageConverter.convert_old_message_to_new(get_task(task['agent_task_id']))
42
215
  end
216
+ task['value']
43
217
  end
44
218
  end
45
219
  end
@@ -38,7 +38,7 @@ module Bosh::Director
38
38
  raise VmAgentIdMissing, "VM `#{vm.cid}' doesn't have an agent id"
39
39
  end
40
40
 
41
- AgentClient.new(vm.agent_id)
41
+ AgentClient.with_defaults(vm.agent_id)
42
42
  end
43
43
 
44
44
  def fetch_logs(user, deployment_name, job, index, options = {})
@@ -36,7 +36,7 @@ module Bosh::Director
36
36
  :retry_methods => { :get_state => retries }
37
37
  }
38
38
  @clients ||= {}
39
- @clients[vm.agent_id] ||= AgentClient.new(vm.agent_id, options)
39
+ @clients[vm.agent_id] ||= AgentClient.with_defaults(vm.agent_id, options)
40
40
  end
41
41
 
42
42
  def agent_timeout_guard(vm, &block)
@@ -151,7 +151,7 @@ module Bosh::Director
151
151
 
152
152
  def get_state(vm)
153
153
  @logger.debug("Requesting current VM state for: #{vm.agent_id}")
154
- agent = AgentClient.new(vm.agent_id)
154
+ agent = AgentClient.with_defaults(vm.agent_id)
155
155
  state = agent.get_state
156
156
 
157
157
  @logger.debug("Received VM state: #{state.pretty_inspect}")
@@ -392,7 +392,7 @@ module Bosh::Director
392
392
 
393
393
  idle_vm.vm.update(:apply_spec => state)
394
394
 
395
- agent = AgentClient.new(idle_vm.vm.agent_id)
395
+ agent = AgentClient.with_defaults(idle_vm.vm.agent_id)
396
396
  agent.apply(state)
397
397
  instance.current_state = state
398
398
  end
@@ -50,7 +50,7 @@ module Bosh::Director
50
50
  # @param [String] agent_id agent id
51
51
  # @return [void]
52
52
  def drain(agent_id)
53
- agent = AgentClient.new(agent_id)
53
+ agent = AgentClient.with_defaults(agent_id)
54
54
 
55
55
  drain_time = agent.drain("shutdown")
56
56
  if drain_time < 0
@@ -457,7 +457,7 @@ module Bosh::Director
457
457
  if @vm.agent_id.nil?
458
458
  raise VmAgentIdMissing, "VM #{@vm.id} is missing agent id"
459
459
  end
460
- @agent = AgentClient.new(@vm.agent_id)
460
+ @agent = AgentClient.with_defaults(@vm.agent_id)
461
461
  end
462
462
  end
463
463
 
@@ -108,7 +108,7 @@ module Bosh::Director
108
108
 
109
109
  if vm && vm.agent_id
110
110
  ignoring_errors_when_forced do
111
- agent = AgentClient.new(vm.agent_id)
111
+ agent = AgentClient.with_defaults(vm.agent_id)
112
112
  agent.stop
113
113
  end
114
114
  end
@@ -117,7 +117,7 @@ module Bosh::Director
117
117
  if disk.active && vm && vm.cid && disk.disk_cid
118
118
  if vm.agent_id
119
119
  ignoring_errors_when_forced do
120
- agent = AgentClient.new(vm.agent_id)
120
+ agent = AgentClient.with_defaults(vm.agent_id)
121
121
  agent.unmount_disk(disk.disk_cid)
122
122
  end
123
123
  end
@@ -44,7 +44,7 @@ module Bosh::Director
44
44
  index = nil
45
45
 
46
46
  begin
47
- agent = AgentClient.new(vm.agent_id, :timeout => TIMEOUT)
47
+ agent = AgentClient.with_defaults(vm.agent_id, :timeout => TIMEOUT)
48
48
  agent_state = agent.get_state(@format)
49
49
  agent_state["networks"].each_value do |network|
50
50
  ips << network["ip"]
@@ -156,7 +156,7 @@ module Bosh::Director
156
156
  @logger.info("Configuring compilation VM: #{vm.cid}")
157
157
 
158
158
  begin
159
- agent = AgentClient.new(vm.agent_id)
159
+ agent = AgentClient.with_defaults(vm.agent_id)
160
160
  agent.wait_until_ready
161
161
 
162
162
  configure_vm(vm, agent, network_settings)
@@ -149,7 +149,7 @@ module Bosh::Director
149
149
  mounted_disk_cid = instance.persistent_disk_cid if instance
150
150
  end
151
151
 
152
- agent = AgentClient.new(vm.agent_id, agent_options)
152
+ agent = AgentClient.with_defaults(vm.agent_id, agent_options)
153
153
  begin
154
154
  state = agent.get_state
155
155
 
@@ -54,7 +54,7 @@ module Bosh::Director
54
54
  vm = VmCreator.new.create(deployment, stemcell, @resource_pool.cloud_properties,
55
55
  idle_vm.network_settings, nil, @resource_pool.env)
56
56
 
57
- agent = AgentClient.new(vm.agent_id)
57
+ agent = AgentClient.with_defaults(vm.agent_id)
58
58
  agent.wait_until_ready
59
59
 
60
60
  update_state(agent, vm, idle_vm)
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Bosh
4
4
  module Director
5
- VERSION = '1.5.0.pre.1269'
5
+ VERSION = '1.5.0.pre.1274'
6
6
  end
7
7
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: bosh-director
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.5.0.pre.1269
4
+ version: 1.5.0.pre.1274
5
5
  prerelease: 6
6
6
  platform: ruby
7
7
  authors:
@@ -34,7 +34,7 @@ dependencies:
34
34
  requirements:
35
35
  - - ~>
36
36
  - !ruby/object:Gem::Version
37
- version: 1.5.0.pre.1269
37
+ version: 1.5.0.pre.1274
38
38
  type: :runtime
39
39
  prerelease: false
40
40
  version_requirements: !ruby/object:Gem::Requirement
@@ -42,7 +42,7 @@ dependencies:
42
42
  requirements:
43
43
  - - ~>
44
44
  - !ruby/object:Gem::Version
45
- version: 1.5.0.pre.1269
45
+ version: 1.5.0.pre.1274
46
46
  - !ruby/object:Gem::Dependency
47
47
  name: bosh-core
48
48
  requirement: !ruby/object:Gem::Requirement
@@ -50,7 +50,7 @@ dependencies:
50
50
  requirements:
51
51
  - - ~>
52
52
  - !ruby/object:Gem::Version
53
- version: 1.5.0.pre.1269
53
+ version: 1.5.0.pre.1274
54
54
  type: :runtime
55
55
  prerelease: false
56
56
  version_requirements: !ruby/object:Gem::Requirement
@@ -58,7 +58,7 @@ dependencies:
58
58
  requirements:
59
59
  - - ~>
60
60
  - !ruby/object:Gem::Version
61
- version: 1.5.0.pre.1269
61
+ version: 1.5.0.pre.1274
62
62
  - !ruby/object:Gem::Dependency
63
63
  name: bosh_common
64
64
  requirement: !ruby/object:Gem::Requirement
@@ -66,7 +66,7 @@ dependencies:
66
66
  requirements:
67
67
  - - ~>
68
68
  - !ruby/object:Gem::Version
69
- version: 1.5.0.pre.1269
69
+ version: 1.5.0.pre.1274
70
70
  type: :runtime
71
71
  prerelease: false
72
72
  version_requirements: !ruby/object:Gem::Requirement
@@ -74,7 +74,7 @@ dependencies:
74
74
  requirements:
75
75
  - - ~>
76
76
  - !ruby/object:Gem::Version
77
- version: 1.5.0.pre.1269
77
+ version: 1.5.0.pre.1274
78
78
  - !ruby/object:Gem::Dependency
79
79
  name: bosh_cpi
80
80
  requirement: !ruby/object:Gem::Requirement
@@ -82,7 +82,7 @@ dependencies:
82
82
  requirements:
83
83
  - - ~>
84
84
  - !ruby/object:Gem::Version
85
- version: 1.5.0.pre.1269
85
+ version: 1.5.0.pre.1274
86
86
  type: :runtime
87
87
  prerelease: false
88
88
  version_requirements: !ruby/object:Gem::Requirement
@@ -90,7 +90,7 @@ dependencies:
90
90
  requirements:
91
91
  - - ~>
92
92
  - !ruby/object:Gem::Version
93
- version: 1.5.0.pre.1269
93
+ version: 1.5.0.pre.1274
94
94
  - !ruby/object:Gem::Dependency
95
95
  name: bosh_openstack_cpi
96
96
  requirement: !ruby/object:Gem::Requirement
@@ -98,7 +98,7 @@ dependencies:
98
98
  requirements:
99
99
  - - ~>
100
100
  - !ruby/object:Gem::Version
101
- version: 1.5.0.pre.1269
101
+ version: 1.5.0.pre.1274
102
102
  type: :runtime
103
103
  prerelease: false
104
104
  version_requirements: !ruby/object:Gem::Requirement
@@ -106,7 +106,7 @@ dependencies:
106
106
  requirements:
107
107
  - - ~>
108
108
  - !ruby/object:Gem::Version
109
- version: 1.5.0.pre.1269
109
+ version: 1.5.0.pre.1274
110
110
  - !ruby/object:Gem::Dependency
111
111
  name: bosh_aws_cpi
112
112
  requirement: !ruby/object:Gem::Requirement
@@ -114,7 +114,7 @@ dependencies:
114
114
  requirements:
115
115
  - - ~>
116
116
  - !ruby/object:Gem::Version
117
- version: 1.5.0.pre.1269
117
+ version: 1.5.0.pre.1274
118
118
  type: :runtime
119
119
  prerelease: false
120
120
  version_requirements: !ruby/object:Gem::Requirement
@@ -122,7 +122,7 @@ dependencies:
122
122
  requirements:
123
123
  - - ~>
124
124
  - !ruby/object:Gem::Version
125
- version: 1.5.0.pre.1269
125
+ version: 1.5.0.pre.1274
126
126
  - !ruby/object:Gem::Dependency
127
127
  name: bosh_vsphere_cpi
128
128
  requirement: !ruby/object:Gem::Requirement
@@ -130,7 +130,7 @@ dependencies:
130
130
  requirements:
131
131
  - - ~>
132
132
  - !ruby/object:Gem::Version
133
- version: 1.5.0.pre.1269
133
+ version: 1.5.0.pre.1274
134
134
  type: :runtime
135
135
  prerelease: false
136
136
  version_requirements: !ruby/object:Gem::Requirement
@@ -138,7 +138,7 @@ dependencies:
138
138
  requirements:
139
139
  - - ~>
140
140
  - !ruby/object:Gem::Version
141
- version: 1.5.0.pre.1269
141
+ version: 1.5.0.pre.1274
142
142
  - !ruby/object:Gem::Dependency
143
143
  name: eventmachine
144
144
  requirement: !ruby/object:Gem::Requirement
@@ -445,7 +445,7 @@ dependencies:
445
445
  version: '1.0'
446
446
  description: ! 'BOSH Director
447
447
 
448
- 12f8ea'
448
+ 6ac74e'
449
449
  email: support@cloudfoundry.com
450
450
  executables:
451
451
  - bosh-director
@@ -523,7 +523,6 @@ files:
523
523
  - lib/bosh/director/app.rb
524
524
  - lib/bosh/director/blob_util.rb
525
525
  - lib/bosh/director/blobstores.rb
526
- - lib/bosh/director/client.rb
527
526
  - lib/bosh/director/cloudcheck_helper.rb
528
527
  - lib/bosh/director/compile_task.rb
529
528
  - lib/bosh/director/compiled_package_downloader.rb
@@ -1,156 +0,0 @@
1
- # Copyright (c) 2009-2012 VMware, Inc.
2
-
3
- module Bosh::Director
4
- class Client
5
-
6
- attr_accessor :id
7
-
8
- def initialize(service_name, client_id, options = {})
9
- @service_name = service_name
10
- @client_id = client_id
11
- @nats_rpc = Config.nats_rpc
12
- @timeout = options[:timeout] || 45
13
- @logger = Config.logger
14
- @retry_methods = options[:retry_methods] || {}
15
-
16
- if options[:credentials]
17
- @encryption_handler =
18
- Bosh::Core::EncryptionHandler.new(@client_id, options[:credentials])
19
- end
20
-
21
- @resource_manager = Api::ResourceManager.new
22
- end
23
-
24
- def method_missing(method_name, *args)
25
- retries = @retry_methods[method_name] || 0
26
- begin
27
- handle_method(method_name, args)
28
- rescue RpcTimeout
29
- if retries > 0
30
- retries -= 1
31
- retry
32
- end
33
- raise
34
- end
35
- end
36
-
37
- def wait_until_ready(deadline = 600)
38
- old_timeout = @timeout
39
- @timeout = 1.0
40
- @deadline = Time.now.to_i + deadline
41
-
42
- begin
43
- ping
44
- rescue RpcTimeout
45
- retry if @deadline - Time.now.to_i > 0
46
- raise RpcTimeout, "Timed out pinging to #{@client_id} after #{deadline} seconds"
47
- rescue RpcRemoteException => e
48
- retry if e.message =~ /^restarting agent/ && @deadline - Time.now.to_i > 0
49
- raise e
50
- ensure
51
- @timeout = old_timeout
52
- end
53
- end
54
-
55
- def handle_method(method_name, args)
56
- result = {}
57
- result.extend(MonitorMixin)
58
-
59
- cond = result.new_cond
60
- timeout_time = Time.now.to_f + @timeout
61
-
62
- request = {:method => method_name, :arguments => args}
63
-
64
- if @encryption_handler
65
- @logger.info("Request: #{request}")
66
- request = {"encrypted_data" => @encryption_handler.encrypt(request)}
67
- request["session_id"] = @encryption_handler.session_id
68
- end
69
-
70
- recipient = "#{@service_name}.#{@client_id}"
71
-
72
- request_id = @nats_rpc.send_request(recipient, request) do |response|
73
- if @encryption_handler
74
- begin
75
- response = @encryption_handler.decrypt(response["encrypted_data"])
76
- rescue Bosh::Core::EncryptionHandler::CryptError => e
77
- response["exception"] = "CryptError: #{e.inspect} #{e.backtrace}"
78
- end
79
- @logger.info("Response: #{response}")
80
- end
81
-
82
- result.synchronize do
83
- inject_compile_log(response)
84
- result.merge!(response)
85
- cond.signal
86
- end
87
- end
88
-
89
- result.synchronize do
90
- while result.empty?
91
- timeout = timeout_time - Time.now.to_f
92
- unless timeout > 0
93
- @nats_rpc.cancel_request(request_id)
94
- raise RpcTimeout,
95
- "Timed out sending `#{method_name}' to #{@client_id} " +
96
- "after #{@timeout} seconds"
97
- end
98
- cond.wait(timeout)
99
- end
100
- end
101
-
102
- if result.has_key?("exception")
103
- raise RpcRemoteException, format_exception(result["exception"])
104
- end
105
-
106
- result["value"]
107
- end
108
-
109
- # Returns formatted exception information
110
- # @param [Hash|#to_s] exception Serialized exception
111
- # @return [String]
112
- def format_exception(exception)
113
- return exception.to_s unless exception.is_a?(Hash)
114
-
115
- msg = exception["message"].to_s
116
-
117
- if exception["backtrace"]
118
- msg += "\n"
119
- msg += Array(exception["backtrace"]).join("\n")
120
- end
121
-
122
- if exception["blobstore_id"]
123
- blob = download_and_delete_blob(exception["blobstore_id"])
124
- msg += "\n"
125
- msg += blob.to_s
126
- end
127
-
128
- msg
129
- end
130
-
131
- private
132
-
133
- # the blob is removed from the blobstore once we have fetched it,
134
- # but if there is a crash before it is injected into the response
135
- # and then logged, there is a chance that we lose it
136
- def inject_compile_log(response)
137
- if response["value"] && response["value"].is_a?(Hash) &&
138
- response["value"]["result"].is_a?(Hash) &&
139
- blob_id = response["value"]["result"]["compile_log_id"]
140
- compile_log = download_and_delete_blob(blob_id)
141
- response["value"]["result"]["compile_log"] = compile_log
142
- end
143
- end
144
-
145
- # Downloads blob and ensures it's deleted from the blobstore
146
- # @param [String] blob_id Blob id
147
- # @return [String] Blob contents
148
- def download_and_delete_blob(blob_id)
149
- blob = @resource_manager.get_resource(blob_id)
150
- blob
151
- ensure
152
- @resource_manager.delete_resource(blob_id)
153
- end
154
-
155
- end
156
- end