Skip to content
This repository was archived by the owner on Jun 2, 2021. It is now read-only.

Commit e544619

Browse files
author
Aakash Shah
committed
Bring back pr cloudfoundry#1558
This reverts commit d1cf638, reversing changes made to 39952cf.
1 parent 17401d8 commit e544619

2 files changed

Lines changed: 115 additions & 83 deletions

File tree

lib/cloud_controller/opi/stager_client.rb

Lines changed: 52 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -10,20 +10,54 @@ class StagerClient < BaseClient
1010
def stage(staging_guid, staging_details)
1111
logger.info('stage.request', staging_guid: staging_guid)
1212

13-
if staging_details.lifecycle.type == VCAP::CloudController::Lifecycles::DOCKER
14-
complete_staging(staging_guid, staging_details)
15-
elsif staging_details.lifecycle.type == VCAP::CloudController::Lifecycles::BUILDPACK
16-
staging_request = to_request(staging_guid, staging_details)
17-
start_staging(staging_guid, staging_request)
18-
else
13+
unless [VCAP::CloudController::Lifecycles::DOCKER, VCAP::CloudController::Lifecycles::BUILDPACK].include?(staging_details.lifecycle.type)
1914
raise("lifecycle type `#{staging_details.lifecycle.type}` is invalid")
2015
end
16+
17+
request = to_request(staging_guid, staging_details)
18+
start_staging(staging_guid, request)
2119
end
2220

2321
def stop_staging(staging_guid); end
2422

2523
private
2624

25+
class BuildpackLifecycle
26+
def initialize(action_builder, staging_guid, cc_uploader_url)
27+
@action_builder = action_builder
28+
@staging_guid = staging_guid
29+
@cc_uploader_url = cc_uploader_url
30+
end
31+
32+
def to_hash
33+
lifecycle_data = @action_builder.lifecycle_data
34+
droplet_upload_uri = "#{@cc_uploader_url}/v1/droplet/#{@staging_guid}?cc-droplet-upload-uri=#{lifecycle_data[:droplet_upload_uri]}"
35+
{
36+
buildpack_lifecycle: {
37+
droplet_upload_uri: droplet_upload_uri,
38+
app_bits_download_uri: lifecycle_data[:app_bits_download_uri],
39+
buildpacks: lifecycle_data[:buildpacks]
40+
}
41+
}
42+
end
43+
end
44+
45+
class DockerLifecycle
46+
def initialize(staging_details)
47+
@staging_details = staging_details
48+
end
49+
50+
def to_hash
51+
{
52+
docker_lifecycle: {
53+
image: @staging_details.package.image,
54+
registry_username: @staging_details.package.docker_username,
55+
registry_password: @staging_details.package.docker_password
56+
}
57+
}
58+
end
59+
end
60+
2761
def start_staging(staging_guid, staging_request)
2862
payload = MultiJson.dump(staging_request)
2963
response = client.post("/stage/#{staging_guid}", body: payload)
@@ -34,32 +68,11 @@ def start_staging(staging_guid, staging_request)
3468
end
3569
end
3670

37-
def complete_staging(staging_guid, staging_details)
38-
build = VCAP::CloudController::BuildModel.find(guid: staging_guid)
39-
raise CloudController::Errors::ApiError.new_from_details('ResourceNotFound', 'Build not found') if build.nil?
40-
41-
completion_handler = VCAP::CloudController::Diego::Docker::StagingCompletionHandler.new(build)
42-
payload = {
43-
result: {
44-
lifecycle_type: 'docker',
45-
lifecycle_metadata: {
46-
docker_image: staging_details.package.image
47-
},
48-
process_types: { web: '' },
49-
execution_metadata: '{\"cmd\":[],\"ports\":[{\"Port\":8080,\"Protocol\":\"tcp\"}]}'
50-
}
51-
}
52-
completion_handler.staging_complete(payload, staging_details.start_after_staging)
53-
end
54-
5571
def to_request(staging_guid, staging_details)
5672
lifecycle_type = staging_details.lifecycle.type
5773
action_builder = VCAP::CloudController::Diego::LifecycleProtocol.protocol_for_type(lifecycle_type).staging_action_builder(config, staging_details)
58-
lifecycle_data = action_builder.lifecycle_data
59-
60-
cc_uploader_url = config.get(:opi, :cc_uploader_url)
61-
droplet_upload_uri = "#{cc_uploader_url}/v1/droplet/#{staging_guid}?cc-droplet-upload-uri=#{lifecycle_data[:droplet_upload_uri]}"
6274

75+
lifecycle = get_lifecycle(staging_details, staging_guid, action_builder)
6376
{
6477
app_guid: staging_details.package.app_guid,
6578
app_name: staging_details.package.app.name,
@@ -68,19 +81,24 @@ def to_request(staging_guid, staging_details)
6881
org_guid: staging_details.package.app.organization.guid,
6982
space_name: staging_details.package.app.space.name,
7083
space_guid: staging_details.package.app.space.guid,
71-
environment: build_env(staging_details.environment_variables) + action_builder.task_environment_variables,
84+
environment: build_env(staging_details.environment_variables) + action_builder.task_environment_variables.to_a,
7285
completion_callback: staging_completion_callback(staging_details),
73-
lifecycle_data: {
74-
droplet_upload_uri: droplet_upload_uri,
75-
app_bits_download_uri: lifecycle_data[:app_bits_download_uri],
76-
buildpacks: lifecycle_data[:buildpacks]
77-
},
86+
lifecycle: lifecycle,
7887
cpu_weight: VCAP::CloudController::Diego::STAGING_TASK_CPU_WEIGHT,
7988
disk_mb: staging_details.staging_disk_in_mb,
8089
memory_mb: staging_details.staging_memory_in_mb
8190
}
8291
end
8392

93+
def get_lifecycle(staging_details, staging_guid, action_builder)
94+
if staging_details.lifecycle.type == VCAP::CloudController::Lifecycles::DOCKER
95+
DockerLifecycle.new(staging_details)
96+
else
97+
cc_uploader_url = config.get(:opi, :cc_uploader_url)
98+
BuildpackLifecycle.new(action_builder, staging_guid, cc_uploader_url)
99+
end
100+
end
101+
84102
def staging_completion_callback(staging_details)
85103
port = config.get(:tls_port)
86104
scheme = 'https'

spec/unit/lib/cloud_controller/opi/stager_client_spec.rb

Lines changed: 63 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -46,14 +46,17 @@
4646

4747
context 'when staging an app' do
4848
before do
49-
allow(VCAP::CloudController::Diego::Buildpack::LifecycleProtocol).to receive(:new).and_return(lifecycle_protocol)
50-
5149
stub_request(:post, "#{eirini_url}/stage/#{staging_guid}").
5250
to_return(status: 202)
5351
end
5452

5553
context 'when lifecycle type is buildpack' do
5654
let(:lifecycle_type) { VCAP::CloudController::Lifecycles::BUILDPACK }
55+
56+
before do
57+
allow(VCAP::CloudController::Diego::Buildpack::LifecycleProtocol).to receive(:new).and_return(lifecycle_protocol)
58+
end
59+
5760
it 'should send the expected request' do
5861
stager_client.stage(staging_guid, staging_details)
5962
expect(WebMock).to have_requested(:post, "#{eirini_url}/stage/#{staging_guid}").with(body: {
@@ -68,9 +71,12 @@
6871
{ name: 'MEMORY_LIMIT', value: '256m' },
6972
{ name: 'VCAP_SERVICES', value: '{}' }],
7073
completion_callback: 'https://internal_user:internal_password@api.internal.cf:8182/internal/v3/staging//build_completed?start=',
71-
lifecycle_data: { droplet_upload_uri: "http://cc-uploader.service.cf.internal:9091/v1/droplet/#{staging_guid}?cc-droplet-upload-uri=http://upload.me",
72-
app_bits_download_uri: 'http://download.me',
73-
buildpacks: [{ name: 'ruby', key: 'idk', url: 'www.com', skip_detect: false }]
74+
lifecycle: {
75+
buildpack_lifecycle: {
76+
droplet_upload_uri: "http://cc-uploader.service.cf.internal:9091/v1/droplet/#{staging_guid}?cc-droplet-upload-uri=http://upload.me",
77+
app_bits_download_uri: 'http://download.me',
78+
buildpacks: [{ name: 'ruby', key: 'idk', url: 'www.com', skip_detect: false }]
79+
}
7480
},
7581
cpu_weight: VCAP::CloudController::Diego::STAGING_TASK_CPU_WEIGHT,
7682
disk_mb: 100,
@@ -99,9 +105,12 @@
99105
{ name: 'MEMORY_LIMIT', value: '256m' },
100106
{ name: 'VCAP_SERVICES', value: '{}' }],
101107
completion_callback: 'https://internal_user:internal_password@api.internal.cf:8182/internal/v3/staging//build_completed?start=',
102-
lifecycle_data: { droplet_upload_uri: "http://cc-uploader.service.cf.internal:9091/v1/droplet/#{staging_guid}?cc-droplet-upload-uri=http://upload.me",
103-
app_bits_download_uri: 'http://download.me',
104-
buildpacks: [{ name: 'ruby', key: 'idk', url: 'www.com', skip_detect: false }]
108+
lifecycle: {
109+
buildpack_lifecycle: {
110+
droplet_upload_uri: "http://cc-uploader.service.cf.internal:9091/v1/droplet/#{staging_guid}?cc-droplet-upload-uri=http://upload.me",
111+
app_bits_download_uri: 'http://download.me',
112+
buildpacks: [{ name: 'ruby', key: 'idk', url: 'www.com', skip_detect: false }]
113+
}
105114
},
106115
cpu_weight: VCAP::CloudController::Diego::STAGING_TASK_CPU_WEIGHT,
107116
disk_mb: 100,
@@ -125,57 +134,60 @@
125134

126135
context 'when lifecycle type is docker' do
127136
let(:lifecycle_type) { VCAP::CloudController::Lifecycles::DOCKER }
128-
let(:staging_completion_handler) { instance_double(VCAP::CloudController::Diego::Docker::StagingCompletionHandler) }
129-
let(:build_model) { instance_double(VCAP::CloudController::BuildModel) }
130-
let(:payload) {
131-
{
132-
result: {
133-
lifecycle_type: 'docker',
134-
lifecycle_metadata: {
135-
docker_image: 'docker.io/some/image'
136-
},
137-
process_types: { web: '' },
138-
execution_metadata: '{\"cmd\":[],\"ports\":[{\"Port\":8080,\"Protocol\":\"tcp\"}]}'
139-
}
140-
}
141-
}
142-
143-
it 'should not make any http calls to eirini' do
144-
allow(VCAP::CloudController::BuildModel).to receive(:find).and_return(build_model)
145-
allow(VCAP::CloudController::Diego::Docker::StagingCompletionHandler).to receive(:new).and_return(staging_completion_handler)
146-
allow(staging_completion_handler).to receive(:staging_complete)
147137

148-
stager_client.stage(staging_guid, staging_details)
149-
expect(WebMock).not_to have_requested(:any, "#{eirini_url}/stage/#{staging_guid}")
138+
let(:staging_action_builder) do
139+
instance_double(VCAP::CloudController::Diego::Docker::StagingActionBuilder,
140+
task_environment_variables: lifecycle_environment_variables,
141+
)
150142
end
151143

152-
it 'should mark staging as completed' do
153-
expect(VCAP::CloudController::BuildModel).to receive(:find).with(guid: staging_guid).and_return(build_model)
154-
expect(VCAP::CloudController::Diego::Docker::StagingCompletionHandler).to receive(:new).with(build_model).and_return(staging_completion_handler)
155-
expect(staging_completion_handler).to receive(:staging_complete).with(payload, true)
144+
let(:lifecycle_protocol) do
145+
instance_double(VCAP::CloudController::Diego::Docker::LifecycleProtocol,
146+
staging_action_builder: staging_action_builder
147+
)
148+
end
156149

157-
staging_details.start_after_staging = true
158-
stager_client.stage(staging_guid, staging_details)
150+
before do
151+
allow(VCAP::CloudController::Diego::Docker::LifecycleProtocol).to receive(:new).and_return(lifecycle_protocol)
159152
end
160153

161-
context 'when build is not found' do
162-
it 'should raise an error' do
163-
expect(VCAP::CloudController::BuildModel).to receive(:find).with(guid: staging_guid).and_return(nil)
164-
expect {
165-
stager_client.stage(staging_guid, staging_details)
166-
}.to raise_error(CloudController::Errors::ApiError, 'Build not found')
167-
end
154+
it 'should set a docker lifecycle' do
155+
stager_client.stage(staging_guid, staging_details)
156+
expect(WebMock).to have_requested(:post, "#{eirini_url}/stage/#{staging_guid}").with(body: {
157+
app_guid: 'thor',
158+
app_name: 'the_thor',
159+
staging_guid: staging_guid,
160+
org_name: 'some-org',
161+
org_guid: 'some-org-guid',
162+
space_name: 'outer',
163+
space_guid: 'outer-guid',
164+
environment: [{ name: 'VCAP_APPLICATION', value: '{"wow":"pants"}' },
165+
{ name: 'MEMORY_LIMIT', value: '256m' },
166+
{ name: 'VCAP_SERVICES', value: '{}' }],
167+
completion_callback: 'https://internal_user:internal_password@api.internal.cf:8182/internal/v3/staging//build_completed?start=',
168+
lifecycle: {
169+
docker_lifecycle: {
170+
image: 'docker.io/some/image',
171+
registry_username: 'theone',
172+
registry_password: 'notone'
173+
}
174+
},
175+
cpu_weight: VCAP::CloudController::Diego::STAGING_TASK_CPU_WEIGHT,
176+
disk_mb: 100,
177+
memory_mb: 200
178+
}.to_json
179+
)
168180
end
169181
end
182+
end
170183

171-
context 'when lifecycle type is invalid' do
172-
let(:lifecycle_type) { 'dockerpack' }
184+
context 'when lifecycle type is invalid' do
185+
let(:lifecycle_type) { 'dockerpack' }
173186

174-
it 'should raise an error' do
175-
expect {
176-
stager_client.stage(staging_guid, staging_details)
177-
}.to raise_error(RuntimeError, 'lifecycle type `dockerpack` is invalid')
178-
end
187+
it 'should raise an error' do
188+
expect {
189+
stager_client.stage(staging_guid, staging_details)
190+
}.to raise_error(RuntimeError, 'lifecycle type `dockerpack` is invalid')
179191
end
180192
end
181193

@@ -193,6 +205,8 @@ def stub_staging_details(lifecycle_type)
193205
package_model = VCAP::CloudController::PackageModel.make(
194206
type: 'docker',
195207
docker_image: 'docker.io/some/image',
208+
docker_username: 'theone',
209+
docker_password: 'notone',
196210
app: app_model)
197211

198212
staging_details = VCAP::CloudController::Diego::StagingDetails.new

0 commit comments

Comments
 (0)