Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
76 commits
Select commit Hold shift + click to select a range
066ab76
Rename ServiceInstanceUnbinder#unbind => ServiceInstanceUnbinder#dela…
kdeshpan Jan 5, 2015
17ea372
Modify test to ensure that error is propagated in service_binding_spec
kdeshpan Jan 5, 2015
98d0aba
Add standard error handling tests to update_service_plan method
dsabeti Jan 5, 2015
60ab3a7
Move response parsing logic to ResponseParser object
dsabeti Jan 6, 2015
27d8f31
Add retryable jobs
dsabeti Jan 6, 2015
b58ce03
Reduce max_attempts for Deprovision and Unbind jobs
dsabeti Jan 7, 2015
a63bdbf
Fix rubocop errors
dsabeti Jan 7, 2015
80871ea
Retry ServiceInstanceUnbind job
dsabeti Jan 7, 2015
102c7ca
Move ServiceBrokerApiTimeout and ServiceBrokerApiUnreachable into an …
dsabeti Jan 7, 2015
89b72eb
Move ServiceBrokerResponseMalformed into errors directory
dsabeti Jan 7, 2015
c53213d
Move ServiceBrokerApiAuthenticationFailed into errors directory
dsabeti Jan 7, 2015
2997d5b
Move ServiceBrokerBadResponse into errors directory
dsabeti Jan 7, 2015
d3beb2d
Move ServiceBrokerConflict into errors directory
dsabeti Jan 8, 2015
a7cc7d5
service broker http client cannot raise BadResponse error, so do not …
dsabeti Jan 8, 2015
65c5dd5
Add ServiceBrokerRequestRejected error for unhandled 4xx errors
dsabeti Jan 8, 2015
d4f16ff
Add initial paging for v3 apps.
zrob Jan 7, 2015
2c15d4f
Paginate /v3/processes
zrob Jan 7, 2015
ce1da01
Refactor pagination presentation logic into its own class.
luan Jan 8, 2015
22bf04e
Refactor PaginationOptions to be created from request params
zrob Jan 8, 2015
e0a6fa4
Retry deprovision job
dsabeti Jan 8, 2015
09a0b47
Extract UaaClient from Services UaaClientManager
Jan 7, 2015
182a766
User collection endpoints now return usernames in the json response
Jan 7, 2015
f723172
Bump API version to 2.21.0
Jan 7, 2015
b8b7085
Add request ID to ServiceInstanceUnbind job
dsabeti Jan 9, 2015
5ac302d
Refactor ServiceInstanceUnbinder spec
dsabeti Jan 9, 2015
8dfd532
Add request id to ServiceInstanceDeprovision job
wschaefer Jan 9, 2015
885a8f8
Use DelayedJob reschedule_at functionality instead of RetryableJob
wschaefer Jan 9, 2015
8bba6a3
Remove Retryable Job
dsabeti Jan 12, 2015
1a360b2
Add logging to deprovision job
dsabeti Jan 12, 2015
f2d85b4
Merge Unbinder and Deprovisoner into the single OrphanMitigator
dsabeti Jan 12, 2015
146073e
Make orphan mitigator class methods into instance methods
dsabeti Jan 12, 2015
d23704b
Implement POST /v3/apps/:guid/packages
crhino Jan 7, 2015
b486985
Implement DELETE /v3/packages/:guid
jfmyers9 Jan 8, 2015
4e5b683
Return a 404 on POST /v3/apps/:guid/packages if the app does not exist
Jan 8, 2015
23a3f9a
Implement POST /v3/apps/:guid/packages with type docker
jfmyers9 Jan 8, 2015
b473a1d
Respect max_package_size for /v3/apps/:guid/package
Jan 8, 2015
ea83e10
Fix rubocop offenses
jfmyers9 Jan 8, 2015
4f2114e
Implement /v3/packages/:guid/upload
Jan 9, 2015
c628109
Factor apart app and package logic.
jfmyers9 Jan 12, 2015
c75c99a
Package bits can only be uploaded once.
zrob Jan 12, 2015
eda570d
Fix time consistency, use DB time where possible
Jan 13, 2015
b9a1b52
Return state after requesting service instance provision
dsabeti Jan 13, 2015
3635820
Extract versioned_guid from app
sykesm Jan 7, 2015
47a642a
Add etag to desire app messages
sykesm Jan 8, 2015
698b952
Add new bulk endpoints for nsync
sykesm Jan 8, 2015
5167824
Rename format to 'fingerprint'
sykesm Jan 8, 2015
de41ab8
Fix flaky time dependent test
Jan 13, 2015
72a6713
Fix rubocop offense
Jan 13, 2015
0cdb27e
Fix incompatibility with MySQL 5.5 when setting timezone
Jan 13, 2015
a73f846
Upload api_docs after_success and only for the api_docs build
jfmyers9 Jan 13, 2015
e3acff9
Update created_at to not have ON UPDATE CURRENT_TIMESTAMP for mysql
jfmyers9 Jan 13, 2015
ec493f8
Remove message field login from ServiceBrokerConflict Error
dsabeti Jan 13, 2015
5baa59b
Swap Net::HTTP for HTTPClient in ServiceBrokers::V2::HttpClient to av…
Jan 14, 2015
b009554
Respect true, t, false, and f when querying boolean values
jfmyers9 Jan 14, 2015
d19d376
Factor out enqueueing logic from do_delete so that controllers can ca…
Jan 14, 2015
da665b7
Decrease sensitivity on time based test
Jan 14, 2015
315edac
ensure Timecop.return is called after every test
zrob Jan 14, 2015
23930e6
Add `rake db:dev:migrate` and `rake db:dev:rollback` to migrate dev dbs
jfmyers9 Jan 14, 2015
106628d
ServiceBrokerResponseMalformed and ServiceBrokerApiUnreachable are re…
dsabeti Jan 14, 2015
ee7b93b
Backfill tests for response codes from service broker errors
dsabeti Jan 14, 2015
b9ae86a
Reduce unnecessary namespacing
dsabeti Jan 14, 2015
29019f4
Remove unnecessary contexts
dsabeti Jan 14, 2015
452a2a7
Specifying the max on health check timeout if the limit is exceeded
kdeshpan Jan 15, 2015
79bf28c
adding async service instance provisioning
Jan 15, 2015
367d350
Fixed RuboCop offense.
Jan 16, 2015
9df987a
Renamed accept_unavailable to accept_incomplete.
Jan 16, 2015
fee82f3
Set poll interval for service instance fetch job to be 1 minute.
Jan 16, 2015
8f0cabe
Use initializers instead of depending on Struct.new for Job classes
dsabeti Jan 16, 2015
341cea9
Make all jobs inherit from CCJob
wschaefer Jan 16, 2015
1672eed
Wrapper jobs delegate reschedule_at to inner jobs
dsabeti Jan 16, 2015
c6c8514
Rename binding => service_binding
dsabeti Jan 16, 2015
290f08e
Fix paginagion url for nested processes under apps
Jan 16, 2015
e4beab6
Raise proper api error when user tries to upload package bits twice
Jan 19, 2015
62d32d0
Revert time consistency commits.
zrob Jan 20, 2015
b0e4288
Add network egress rules for Diego
Jan 16, 2015
2f39533
Configurable file_descriptors limit for warden container
Dec 29, 2014
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
8 changes: 4 additions & 4 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,13 @@ before_script:
script:
- bundle exec rake $TASKS

after_success:
- "[ $TRAVIS_BRANCH == 'master' -a $UPLOAD_DOCUMENTATION == 'true' ] && travis-artifacts upload --path doc/api --target-path $TRAVIS_BUILD_ID && echo https://s3-us-east-1.amazonaws.com/cc-api-docs/$TRAVIS_BUILD_ID/index.html"

services:
- mysql
- postgresql

after_script: # and this only on success, fail the whole build if it fails
- "[ $TRAVIS_TEST_RESULT == 0 -a $TRAVIS_BRANCH == 'master' ] && travis-artifacts upload --path doc/api --target-path $TRAVIS_BUILD_ID && echo https://s3-us-east-1.amazonaws.com/cc-api-docs/$TRAVIS_BUILD_ID/index.html"

env:
global:
# API Docs
Expand All @@ -39,5 +39,5 @@ env:
- COVERAGE=true DB=postgres TASKS=spec:all
- DB=mysql TASKS=spec:all

- DB=postgres TASKS=spec:api
- DB=postgres TASKS=spec:api UPLOAD_DOCUMENTATION=true
- TASKS=rubocop
34 changes: 34 additions & 0 deletions app/access/v3/package_access.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
module VCAP::CloudController
class PackageModelAccess
include Allowy::AccessControl

def read?(package)
return true if context.roles.admin?

has_read_scope = SecurityContext.scopes.include?('cloud_controller.read')
user_visible = Space.user_visible(context.user).where(guid: package.space_guid).count > 0

has_read_scope && user_visible
end

def create?(_, space)
return true if context.roles.admin?

has_write_scope = SecurityContext.scopes.include?('cloud_controller.write')
is_space_developer = space && space.developers.include?(context.user)
org_active = space && space.organization.active?

has_write_scope && is_space_developer && org_active
end

def delete?(package, space)
create?(package, space)
end

def upload?(package, space)
return true if context.roles.admin?
return false unless FeatureFlag.enabled?('app_bits_upload')
create?(package, space)
end
end
end
15 changes: 15 additions & 0 deletions app/collection_transformers/username_populator.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
module VCAP::CloudController
class UsernamePopulator
attr_reader :uaa_client

def initialize(uaa_client)
@uaa_client = uaa_client
end

def transform(users)
user_ids = users.collect(&:guid)
username_mapping = uaa_client.usernames_for_ids(user_ids)
users.each { |user| user.username = username_mapping[user.guid] }
end
end
end
18 changes: 11 additions & 7 deletions app/controllers/base/model_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ module VCAP::CloudController::RestController
class ModelController < BaseController
include Routes

attr_reader :object_renderer, :collection_renderer

def inject_dependencies(dependencies)
super
@object_renderer = dependencies.fetch(:object_renderer)
Expand Down Expand Up @@ -74,11 +76,15 @@ def update(guid)
def do_delete(obj)
raise_if_has_associations!(obj) if v2_api? && !recursive?
model_deletion_job = Jobs::Runtime::ModelDeletion.new(obj.class, obj.guid)
enqueue_deletion_job(model_deletion_job)
end

def enqueue_deletion_job(deletion_job)
if async?
job = Jobs::Enqueuer.new(model_deletion_job, queue: 'cc-generic').enqueue
job = Jobs::Enqueuer.new(deletion_job, queue: 'cc-generic').enqueue
[HTTP::ACCEPTED, JobPresenter.new(job).to_json]
else
model_deletion_job.perform
deletion_job.perform
[HTTP::NO_CONTENT, nil]
end
end
Expand Down Expand Up @@ -130,7 +136,9 @@ def enumerate_related(guid, name)
@opts
)

collection_renderer.render_json(
associated_controller_instance = CloudController::ControllerFactory.new(@config, @logger, @env, @params, @body, @sinatra).create_controller(associated_controller)

associated_controller_instance.collection_renderer.render_json(
associated_controller,
filtered_dataset,
associated_path,
Expand Down Expand Up @@ -228,10 +236,6 @@ def model
self.class.model
end

protected

attr_reader :object_renderer, :collection_renderer

private

def enumerate_dataset
Expand Down
50 changes: 45 additions & 5 deletions app/controllers/internal/bulk_apps_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
require 'controllers/base/base_controller'
require 'cloud_controller/diego/client'
require 'cloud_controller/internal_api'
require 'cloud_controller/diego/process_guid'

module VCAP::CloudController
class BulkAppsController < RestController::BaseController
Expand All @@ -21,9 +22,34 @@ def bulk_apps
bulk_token = MultiJson.load(params.fetch('token'))
last_id = Integer(bulk_token['id'] || 0)

dependency_locator = ::CloudController::DependencyLocator.instance
runners = dependency_locator.runners
if params['format'] == 'fingerprint'
bulk_fingerprint_format(batch_size, last_id)
else
bulk_desire_app_format(batch_size, last_id)
end
rescue IndexError => e
raise ApiError.new_from_details('BadQueryParameter', e.message)
end

get '/internal/bulk/apps', :bulk_apps

def filtered_bulk_apps
raise ApiError.new_from_details('MessageParseError', 'Missing request body') if body.length == 0
payload = MultiJson.load(body)

apps = runners.diego_apps_from_process_guids(payload)
messages = apps.map { |app| runners.runner_for_app(app).desire_app_message }

MultiJson.dump(messages)
rescue MultiJson::ParseError => e
raise ApiError.new_from_details('MessageParseError', e.message)
end

post '/internal/bulk/apps', :filtered_bulk_apps

private

def bulk_desire_app_format(batch_size, last_id)
apps = runners.diego_apps(batch_size, last_id)
messages = apps.map { |app| runners.runner_for_app(app).desire_app_message }
id_for_next_token = apps.empty? ? nil : apps.last.id
Expand All @@ -32,10 +58,24 @@ def bulk_apps
apps: messages,
token: { 'id' => id_for_next_token }
)
rescue IndexError => e
raise ApiError.new_from_details('BadQueryParameter', e.message)
end

get '/internal/bulk/apps', :bulk_apps
def bulk_fingerprint_format(batch_size, last_id)
id_for_next_token = nil
messages = runners.diego_apps_cache_data(batch_size, last_id).map do |id, guid, version, updated|
id_for_next_token = id
{ 'process_guid' => Diego::ProcessGuid.from(guid, version), 'etag' => updated.to_f.to_s }
end

MultiJson.dump(
fingerprints: messages,
token: { 'id' => id_for_next_token }
)
end

def runners
dependency_locator = ::CloudController::DependencyLocator.instance
@runners ||= dependency_locator.runners
end
end
end
9 changes: 9 additions & 0 deletions app/controllers/runtime/users_controller.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
module VCAP::CloudController
class UsersController < RestController::ModelController
def self.dependencies
[:username_populating_collection_renderer]
end

define_attributes do
attribute :guid, String, exclude_in: :update
attribute :admin, Message::Boolean, default: false
Expand Down Expand Up @@ -33,6 +37,11 @@ def delete(guid)
do_delete(find_guid_and_validate_access(:delete, guid))
end

def inject_dependencies(dependencies)
super
@collection_renderer = dependencies[:username_populating_collection_renderer]
end

define_messages
define_routes
end
Expand Down
19 changes: 4 additions & 15 deletions app/controllers/services/service_bindings_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -24,19 +24,14 @@ def inject_dependencies(dependencies)

post path, :create
def create
json_msg = self.class::CreateMessage.decode(body)

@request_attrs = json_msg.extract(stringify_keys: true)
@request_attrs = self.class::CreateMessage.decode(body).extract(stringify_keys: true)

logger.debug 'cc.create', model: self.class.model_class_name, attributes: request_attrs

raise InvalidRequest unless request_attrs

instance_guid = request_attrs['service_instance_guid']
app_guid = request_attrs['app_guid']

validate_service_instance(instance_guid)
validate_app(app_guid)
validate_service_instance(request_attrs['service_instance_guid'])
validate_app(request_attrs['app_guid'])

service_binding = ServiceBinding.new(@request_attrs)
validate_access(:create, service_binding)
Expand All @@ -63,13 +58,7 @@ def delete(guid)
deletion_job = Jobs::Runtime::ModelDeletion.new(ServiceBinding, guid)
delete_and_audit_job = Jobs::AuditEventJob.new(deletion_job, @services_event_repository, :record_service_binding_event, :delete, service_binding)

if async?
job = Jobs::Enqueuer.new(delete_and_audit_job, queue: 'cc-generic').enqueue
[HTTP::ACCEPTED, JobPresenter.new(job).to_json]
else
delete_and_audit_job.perform
[HTTP::NO_CONTENT, nil]
end
enqueue_deletion_job(delete_and_audit_job)
end

private
Expand Down
8 changes: 1 addition & 7 deletions app/controllers/services/service_instances_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -200,13 +200,7 @@ def delete(guid)
event_method = service_instance.type == 'managed_service_instance' ? :record_service_instance_event : :record_user_provided_service_instance_event
delete_and_audit_job = Jobs::AuditEventJob.new(deletion_job, @services_event_repository, event_method, :delete, service_instance, {})

if async?
job = Jobs::Enqueuer.new(delete_and_audit_job, queue: 'cc-generic').enqueue
[HTTP::ACCEPTED, JobPresenter.new(job).to_json]
else
delete_and_audit_job.perform
[HTTP::NO_CONTENT, nil]
end
enqueue_deletion_job(delete_and_audit_job)
end

def get_filtered_dataset_for_enumeration(model, ds, qp, opts)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,13 +81,7 @@ def delete(guid)
{}
)

if async?
job = Jobs::Enqueuer.new(delete_and_audit_job, queue: 'cc-generic').enqueue
[HTTP::ACCEPTED, JobPresenter.new(job).to_json]
else
delete_and_audit_job.perform
[HTTP::NO_CONTENT, nil]
end
enqueue_deletion_job(delete_and_audit_job)
end

define_messages
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -99,13 +99,7 @@ def delete(guid)
{}
)

if async?
job = Jobs::Enqueuer.new(delete_and_audit_job, queue: 'cc-generic').enqueue
[HTTP::ACCEPTED, JobPresenter.new(job).to_json]
else
delete_and_audit_job.perform
[HTTP::NO_CONTENT, nil]
end
enqueue_deletion_job(delete_and_audit_job)
end

define_messages
Expand Down
14 changes: 13 additions & 1 deletion app/controllers/v3/apps_controller.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
require 'presenters/v3/app_presenter'
require 'handlers/processes_handler'
require 'handlers/apps_handler'
require 'cloud_controller/paging/pagination_options'

module VCAP::CloudController
class AppsV3Controller < RestController::BaseController
Expand All @@ -15,6 +16,14 @@ def inject_dependencies(dependencies)
@process_presenter = dependencies[:process_presenter]
end

get '/v3/apps', :list
def list
pagination_options = PaginationOptions.from_params(params)
paginated_result = @app_handler.list(pagination_options, @access_context)

[HTTP::OK, @app_presenter.present_json_list(paginated_result)]
end

get '/v3/apps/:guid', :show
def show(guid)
app = @app_handler.show(guid, @access_context)
Expand Down Expand Up @@ -73,7 +82,10 @@ def list_processes(guid)
app = @app_handler.show(guid, @access_context)
app_not_found! if app.nil?

[HTTP::OK, @process_presenter.present_json_list(app.processes)]
pagination_options = PaginationOptions.from_params(params)
paginated_result = @process_handler.list(pagination_options, @access_context, app_guid: app.guid)

[HTTP::OK, @process_presenter.present_json_list(paginated_result, "/v3/apps/#{guid}/processes")]
end

put '/v3/apps/:guid/processes', :add_process
Expand Down
Loading