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

Commit 1d4b218

Browse files
reidmitbelinda-liu
andcommitted
v3: add clear_buildpack_cache endpoint
`POST /v3/admin/actions/clear_buildpack_cache` [#163341383] Co-authored-by: Reid Mitchell <rmitchell@pivotal.io> Co-authored-by: Belinda Liu <bliu@pivotal.io>
1 parent e931079 commit 1d4b218

7 files changed

Lines changed: 175 additions & 0 deletions

File tree

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
require 'jobs/v3/buildpack_cache_cleanup'
2+
3+
class AdminActionsController < ApplicationController
4+
def clear_buildpack_cache
5+
unauthorized! unless permission_queryer.can_write_globally?
6+
7+
pollable_job = Jobs::Enqueuer.new(Jobs::V3::BuildpackCacheCleanup.new, queue: Jobs::Queues.generic).enqueue_pollable
8+
head :accepted, 'Location' => url_builder.build_url(path: "/v3/jobs/#{pollable_job.guid}")
9+
end
10+
end
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
module VCAP::CloudController
2+
module Jobs
3+
module V3
4+
class BuildpackCacheCleanup < VCAP::CloudController::Jobs::CCJob
5+
def perform
6+
logger = Steno.logger('cc.background')
7+
logger.info('Attempting cleanup of buildpack_cache blobstore')
8+
9+
blobstore = CloudController::DependencyLocator.instance.buildpack_cache_blobstore
10+
blobstore.delete_all
11+
end
12+
13+
def job_name_in_configuration
14+
:buildpack_cache_cleanup
15+
end
16+
17+
def display_name
18+
'admin.clear_buildpack_cache'
19+
end
20+
21+
def max_attempts
22+
3
23+
end
24+
25+
def resource_guid
26+
''
27+
end
28+
29+
def resource_type
30+
''
31+
end
32+
end
33+
end
34+
end
35+
end

app/models/runtime/pollable_job_model.rb

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@ def complete?
1515
end
1616

1717
def resource_exists?
18+
return false if resource_type.empty?
19+
1820
model = case resource_type
1921
when 'role'
2022
Role
@@ -25,6 +27,7 @@ def resource_exists?
2527
else
2628
Sequel::Model(ActiveSupport::Inflector.pluralize(resource_type).to_sym)
2729
end
30+
2831
!!model.find(guid: resource_guid)
2932
end
3033

config/routes.rb

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
Rails.application.routes.draw do
22
get '/', to: 'root#v3_root'
33

4+
# admin actions
5+
post '/admin/actions/clear_buildpack_cache', to: 'admin_actions#clear_buildpack_cache'
6+
47
# apps
58
get '/apps', to: 'apps_v3#index'
69
post '/apps', to: 'apps_v3#create'

spec/request/admin_actions_spec.rb

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
require 'spec_helper'
2+
require 'request_spec_shared_examples'
3+
4+
RSpec.describe 'admin actions' do
5+
let(:space) { VCAP::CloudController::Space.make }
6+
let(:org) { space.organization }
7+
let(:user) { VCAP::CloudController::User.make }
8+
let(:admin_header) { admin_headers_for(user) }
9+
10+
describe 'POST /v3/admin/actions/clear_buildpack_cache' do
11+
let(:api_call) { lambda { |user_headers| post '/v3/admin/actions/clear_buildpack_cache', {}, user_headers } }
12+
13+
let(:expected_codes_and_responses) do
14+
h = Hash.new(
15+
code: 403,
16+
)
17+
h['admin'] = {
18+
code: 202,
19+
}
20+
h.freeze
21+
end
22+
23+
it_behaves_like 'permissions for single object endpoint', ALL_PERMISSIONS do
24+
let(:after_request_check) do
25+
lambda do
26+
job_guid = last_response.headers['Location'].gsub("#{link_prefix}/v3/jobs/", '')
27+
get "/v3/jobs/#{job_guid}", {}, admin_headers
28+
expect(last_response).to have_status_code(200)
29+
30+
execute_all_jobs(expected_successes: 1, expected_failures: 0)
31+
end
32+
end
33+
end
34+
end
35+
end
Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
require 'spec_helper'
2+
3+
module VCAP::CloudController
4+
module Jobs::V3
5+
RSpec.describe BuildpackCacheCleanup, job_context: :worker do
6+
let(:cc_addr) { '1.2.3.4' }
7+
let(:cc_port) { 5678 }
8+
let(:orphan_key) { 'orphan-key' }
9+
let(:buildpack_cache_key) { 'another-cache-key' }
10+
let(:droplet_key) { 'droplet-key' }
11+
let(:file) { File.expand_path('../../../fixtures/good.zip', File.dirname(__FILE__)) }
12+
let(:workspace) { Dir.mktmpdir }
13+
14+
let(:blobstore_config) do
15+
{
16+
external_host: cc_addr,
17+
tls_port: cc_port,
18+
droplets: {
19+
droplet_directory_key: 'cc-droplets',
20+
fog_connection: {
21+
provider: 'Local',
22+
local_root: Dir.mktmpdir('droplets', workspace)
23+
}
24+
},
25+
directories: {
26+
tmpdir: Dir.mktmpdir('tmpdir', workspace)
27+
},
28+
index: 99,
29+
name: 'api_z1'
30+
}
31+
end
32+
33+
subject(:job) do
34+
BuildpackCacheCleanup.new
35+
end
36+
37+
before do
38+
TestConfig.override(blobstore_config)
39+
end
40+
41+
let(:blobstore) do
42+
CloudController::DependencyLocator.instance.buildpack_cache_blobstore
43+
end
44+
45+
let(:droplet_blobstore) do
46+
CloudController::DependencyLocator.instance.droplet_blobstore
47+
end
48+
49+
after do
50+
FileUtils.rm_rf(workspace)
51+
end
52+
53+
it 'deletes everything from the buildpack_cache directory' do
54+
Fog.unmock!
55+
blobstore.cp_to_blobstore(file, orphan_key)
56+
blobstore.cp_to_blobstore(file, buildpack_cache_key)
57+
58+
expect(blobstore.exists?(orphan_key)).to be_truthy
59+
expect(blobstore.exists?(buildpack_cache_key)).to be_truthy
60+
61+
job.perform
62+
63+
expect(blobstore.exists?(orphan_key)).to be_falsey
64+
expect(blobstore.exists?(buildpack_cache_key)).to be_falsey
65+
end
66+
67+
it 'does not delete any droplets' do
68+
Fog.unmock!
69+
blobstore.cp_to_blobstore(file, orphan_key)
70+
droplet_blobstore.cp_to_blobstore(file, droplet_key)
71+
72+
expect(blobstore.exists?(orphan_key)).to be_truthy
73+
expect(droplet_blobstore.exists?(droplet_key)).to be_truthy
74+
75+
job.perform
76+
77+
expect(blobstore.exists?(orphan_key)).to be_falsey
78+
expect(droplet_blobstore.exists?(droplet_key)).to be_truthy
79+
end
80+
81+
it { is_expected.to be_a_valid_job }
82+
end
83+
end
84+
end

spec/unit/models/runtime/pollable_job_model_spec.rb

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,11 @@ module VCAP::CloudController
5656
expect(job.resource_exists?).to be(false)
5757
end
5858

59+
it 'returns false if the resource type is empty' do
60+
job = PollableJobModel.make(resource_type: '', resource_guid: '')
61+
expect(job.resource_exists?).to be(false)
62+
end
63+
5964
context 'when the resource is a special case' do
6065
it 'returns true if the resource exists' do
6166
organization_quota = QuotaDefinition.make

0 commit comments

Comments
 (0)