Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion app/actions/buildpack_upload.rb
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
module VCAP::CloudController
class BuildpackUpload
def initialize(user_audit_info)
@user_audit_info = user_audit_info
end

def upload_async(message:, buildpack:, config:)
logger.info("uploading buildpacks bits for buildpack #{buildpack.guid}")

upload_job = Jobs::V3::BuildpackBits.new(buildpack.guid, message.bits_path, message.bits_name)
upload_job = Jobs::V3::BuildpackBits.new(buildpack.guid, message.bits_path, message.bits_name, @user_audit_info, message.audit_hash)
Jobs::Enqueuer.new(queue: Jobs::Queues.local(config)).enqueue_pollable(upload_job)
end

Expand Down
2 changes: 1 addition & 1 deletion app/controllers/v3/buildpacks_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ def upload

unprocessable!('Buildpack is locked') if buildpack.locked

pollable_job = BuildpackUpload.new.upload_async(
pollable_job = BuildpackUpload.new(user_audit_info).upload_async(
message: message,
buildpack: buildpack,
config: configuration
Expand Down
9 changes: 7 additions & 2 deletions app/jobs/v3/buildpack_bits.rb
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
require 'cloud_controller/upload_buildpack'
require 'repositories/buildpack_event_repository'

module VCAP::CloudController
module Jobs
Expand All @@ -7,10 +8,12 @@ class BuildpackBits
attr_reader :buildpack_guid
alias_method :resource_guid, :buildpack_guid

def initialize(buildpack_guid, buildpack_bits_path, buildpack_bits_name)
def initialize(buildpack_guid, buildpack_bits_path, buildpack_bits_name, user_audit_info=nil, request_attrs=nil)
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

note Make new parameters optional on job, incase an existing job has been serialised but yet to be processed during an upgrade.

@buildpack_guid = buildpack_guid
@file_path = buildpack_bits_path
@file_name = buildpack_bits_name
@user_audit_info = user_audit_info
@request_attrs = request_attrs
end

def perform
Expand All @@ -19,7 +22,9 @@ def perform
buildpack_blobstore = CloudController::DependencyLocator.instance.buildpack_blobstore
buildpack = Buildpack.find(guid: buildpack_guid)

VCAP::CloudController::UploadBuildpack.new(buildpack_blobstore).upload_buildpack(buildpack, file_path, file_name)
upload_successful = VCAP::CloudController::UploadBuildpack.new(buildpack_blobstore).upload_buildpack(buildpack, file_path, file_name)

Repositories::BuildpackEventRepository.new.record_buildpack_upload(buildpack, @user_audit_info, @request_attrs || {}) if upload_successful && @user_audit_info
ensure
FileUtils.rm_f(file_path)
end
Expand Down
19 changes: 19 additions & 0 deletions app/repositories/buildpack_event_repository.rb
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,25 @@ def record_buildpack_delete(buildpack, user_audit_info)
metadata: {}
)
end

def record_buildpack_upload(buildpack, user_audit_info, request_attrs)
Event.create(
type: EventTypes::BUILDPACK_UPLOAD,
actee: buildpack.guid,
actee_type: 'buildpack',
actee_name: buildpack.name,
actor: user_audit_info.user_guid,
actor_type: 'user',
actor_name: user_audit_info.user_email,
actor_username: user_audit_info.user_name,
timestamp: Sequel::CURRENT_TIMESTAMP,
space_guid: '',
organization_guid: '',
metadata: {
request: request_attrs
}
)
end
end
end
end
1 change: 1 addition & 0 deletions app/repositories/event_types.rb
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ class EventTypesError < StandardError
BUILDPACK_CREATE = 'audit.buildpack.create'.freeze,
BUILDPACK_UPDATE = 'audit.buildpack.update'.freeze,
BUILDPACK_DELETE = 'audit.buildpack.delete'.freeze,
BUILDPACK_UPLOAD = 'audit.buildpack.upload'.freeze,

SERVICE_CREATE = 'audit.service.create'.freeze,
SERVICE_UPDATE = 'audit.service.update'.freeze,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ For more information, see the [Cloud Foundry docs](https://docs.cloudfoundry.org
- `audit.buildpack.create`
- `audit.buildpack.delete`
- `audit.buildpack.update`
- `audit.buildpack.upload`

##### Organization lifecycle
- `audit.organization.create`
Expand Down
11 changes: 9 additions & 2 deletions spec/unit/actions/buildpack_upload_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,12 @@

module VCAP::CloudController
RSpec.describe BuildpackUpload do
subject(:buildpack_upload) { BuildpackUpload.new }
let(:user) { User.make }
let(:user_email) { 'user@example.com' }
let(:user_name) { 'user-name' }
let(:user_audit_info) { UserAuditInfo.new(user_guid: user.guid, user_email: user_email, user_name: user_name) }

subject(:buildpack_upload) { BuildpackUpload.new(user_audit_info) }

describe '#upload_async' do
let!(:buildpack) { VCAP::CloudController::Buildpack.create_from_hash({ name: 'upload_binary_buildpack', stack: nil, position: 0 }) }
Expand Down Expand Up @@ -37,7 +42,9 @@ module VCAP::CloudController
expect(Jobs::V3::BuildpackBits).to receive(:new).with(
buildpack.guid,
'/tmp/path',
'buildpack.zip'
'buildpack.zip',
user_audit_info,
message.audit_hash
).and_call_original
buildpack_upload.upload_async(message:, buildpack:, config:)
end
Expand Down
62 changes: 62 additions & 0 deletions spec/unit/jobs/v3/buildpack_bits_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,11 @@ module Jobs::V3
let(:filename) { 'buildpack.zip' }
let!(:buildpack) { Buildpack.make }
let(:buildpack_guid) { buildpack.guid }
let(:user) { User.make }
let(:user_email) { 'user@example.com' }
let(:user_name) { 'user-name' }
let(:user_audit_info) { UserAuditInfo.new(user_guid: user.guid, user_email: user_email, user_name: user_name) }
let(:request_attrs) { { 'bits_name' => filename } }

subject(:job) do
BuildpackBits.new(buildpack_guid, uploaded_path, filename)
Expand All @@ -27,6 +32,63 @@ module Jobs::V3
it 'knows its job name' do
expect(job.job_name_in_configuration).to equal(:buildpack_bits)
end

context 'when user_audit_info is provided' do
subject(:job) do
BuildpackBits.new(buildpack_guid, uploaded_path, filename, user_audit_info, request_attrs)
end

it 'creates an audit event when upload is successful' do
uploader = instance_double(UploadBuildpack)
allow(UploadBuildpack).to receive(:new).and_return(uploader)
allow(uploader).to receive(:upload_buildpack).and_return(true)
allow(FileUtils).to receive(:rm_f)

expect do
job.perform
end.to change(Event, :count).by(1)

event = Event.last
expect(event.values).to include(
type: 'audit.buildpack.upload',
actee: buildpack.guid,
actee_type: 'buildpack',
actee_name: buildpack.name,
actor: user_audit_info.user_guid,
actor_type: 'user',
actor_name: user_audit_info.user_email,
actor_username: user_audit_info.user_name,
space_guid: '',
organization_guid: ''
)
expect(event.metadata).to eq({ 'request' => request_attrs })
expect(event.timestamp).to be
end

it 'does not create an audit event when upload fails' do
uploader = instance_double(UploadBuildpack)
allow(UploadBuildpack).to receive(:new).and_return(uploader)
allow(uploader).to receive(:upload_buildpack).and_return(false)
allow(FileUtils).to receive(:rm_f)

expect do
job.perform
end.not_to change(Event, :count)
end
end

context 'when user_audit_info is not provided' do
it 'does not create an audit event' do
uploader = instance_double(UploadBuildpack)
allow(UploadBuildpack).to receive(:new).and_return(uploader)
allow(uploader).to receive(:upload_buildpack).and_return(true)
allow(FileUtils).to receive(:rm_f)

expect do
job.perform
end.not_to change(Event, :count)
end
end
end
end
end
Expand Down
89 changes: 89 additions & 0 deletions spec/unit/repositories/buildpack_event_repository_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
require 'spec_helper'
require 'repositories/buildpack_event_repository'

module VCAP::CloudController
module Repositories
RSpec.describe BuildpackEventRepository do
let(:request_attrs) { { 'name' => 'new-buildpack' } }
let(:user) { User.make }
let(:buildpack) { Buildpack.make }
let(:user_email) { 'email address' }
let(:user_name) { 'user name' }
let(:user_audit_info) { UserAuditInfo.new(user_email: user_email, user_guid: user.guid, user_name: user_name) }

subject(:buildpack_event_repository) { BuildpackEventRepository.new }

describe '#record_buildpack_create' do
it 'records event correctly' do
event = buildpack_event_repository.record_buildpack_create(buildpack, user_audit_info, request_attrs)
event.reload
expect(event.space_guid).to eq('')
expect(event.organization_guid).to eq('')
expect(event.type).to eq('audit.buildpack.create')
expect(event.actee).to eq(buildpack.guid)
expect(event.actee_type).to eq('buildpack')
expect(event.actee_name).to eq(buildpack.name)
expect(event.actor).to eq(user.guid)
expect(event.actor_type).to eq('user')
expect(event.actor_name).to eq(user_email)
expect(event.actor_username).to eq(user_name)
expect(event.metadata).to eq({ 'request' => request_attrs })
end
end

describe '#record_buildpack_update' do
it 'records event correctly' do
event = buildpack_event_repository.record_buildpack_update(buildpack, user_audit_info, request_attrs)
event.reload
expect(event.space_guid).to eq('')
expect(event.organization_guid).to eq('')
expect(event.type).to eq('audit.buildpack.update')
expect(event.actee).to eq(buildpack.guid)
expect(event.actee_type).to eq('buildpack')
expect(event.actee_name).to eq(buildpack.name)
expect(event.actor).to eq(user.guid)
expect(event.actor_type).to eq('user')
expect(event.actor_name).to eq(user_email)
expect(event.actor_username).to eq(user_name)
expect(event.metadata).to eq({ 'request' => request_attrs })
end
end

describe '#record_buildpack_delete' do
it 'records event correctly' do
event = buildpack_event_repository.record_buildpack_delete(buildpack, user_audit_info)
event.reload
expect(event.space_guid).to eq('')
expect(event.organization_guid).to eq('')
expect(event.type).to eq('audit.buildpack.delete')
expect(event.actee).to eq(buildpack.guid)
expect(event.actee_type).to eq('buildpack')
expect(event.actee_name).to eq(buildpack.name)
expect(event.actor).to eq(user.guid)
expect(event.actor_type).to eq('user')
expect(event.actor_name).to eq(user_email)
expect(event.actor_username).to eq(user_name)
expect(event.metadata).to eq({})
end
end

describe '#record_buildpack_upload' do
it 'records event correctly' do
event = buildpack_event_repository.record_buildpack_upload(buildpack, user_audit_info, request_attrs)
event.reload
expect(event.space_guid).to eq('')
expect(event.organization_guid).to eq('')
expect(event.type).to eq('audit.buildpack.upload')
expect(event.actee).to eq(buildpack.guid)
expect(event.actee_type).to eq('buildpack')
expect(event.actee_name).to eq(buildpack.name)
expect(event.actor).to eq(user.guid)
expect(event.actor_type).to eq('user')
expect(event.actor_name).to eq(user_email)
expect(event.actor_username).to eq(user_name)
expect(event.metadata).to eq({ 'request' => request_attrs })
end
end
end
end
end
1 change: 1 addition & 0 deletions spec/unit/repositories/event_types_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ module Repositories
'audit.buildpack.create',
'audit.buildpack.update',
'audit.buildpack.delete',
'audit.buildpack.upload',
'audit.service.create',
'audit.service.update',
'audit.service.delete',
Expand Down