Skip to content

Commit

Permalink
[RFC0030 - 2] File-based service bindings app feature (#3997)
Browse files Browse the repository at this point in the history
* Add presenter for file-based-service-bindings app feature

* Adapt AppFeaturesController and AppFeatureUpdate

* Add api docs for file-based-service-bindings app feature
  • Loading branch information
philippthun authored Dec 3, 2024
1 parent 5e77dab commit 3e7021d
Show file tree
Hide file tree
Showing 9 changed files with 123 additions and 10 deletions.
2 changes: 2 additions & 0 deletions app/actions/app_feature_update.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ def self.update(feature_name, app, message)
app.update(enable_ssh: message.enabled)
when 'revisions'
app.update(revisions_enabled: message.enabled)
when 'file-based-service-bindings'
app.update(file_based_service_bindings_enabled: message.enabled)
end
end
end
Expand Down
10 changes: 7 additions & 3 deletions app/controllers/v3/app_features_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
require 'controllers/v3/mixins/app_sub_resource'
require 'presenters/v3/app_ssh_feature_presenter'
require 'presenters/v3/app_revisions_feature_presenter'
require 'presenters/v3/app_file_based_service_bindings_feature_presenter'
require 'presenters/v3/app_ssh_status_presenter'
require 'actions/app_feature_update'

Expand All @@ -10,8 +11,9 @@ class AppFeaturesController < ApplicationController

SSH_FEATURE = 'ssh'.freeze
REVISIONS_FEATURE = 'revisions'.freeze
FILE_BASED_SERVICE_BINDINGS_FEATURE = 'file-based-service-bindings'.freeze

TRUSTED_APP_FEATURES = [SSH_FEATURE].freeze
TRUSTED_APP_FEATURES = [SSH_FEATURE, FILE_BASED_SERVICE_BINDINGS_FEATURE].freeze
UNTRUSTED_APP_FEATURES = [REVISIONS_FEATURE].freeze
APP_FEATURES = (TRUSTED_APP_FEATURES + UNTRUSTED_APP_FEATURES).freeze

Expand Down Expand Up @@ -80,15 +82,17 @@ def present_unpagination_hash(result, path)
def feature_presenter_for(feature_name, app)
presenters = {
SSH_FEATURE => Presenters::V3::AppSshFeaturePresenter,
REVISIONS_FEATURE => Presenters::V3::AppRevisionsFeaturePresenter
REVISIONS_FEATURE => Presenters::V3::AppRevisionsFeaturePresenter,
FILE_BASED_SERVICE_BINDINGS_FEATURE => Presenters::V3::AppFileBasedServiceBindingsFeaturePresenter
}
presenters[feature_name].new(app)
end

def presented_app_features(app)
[
Presenters::V3::AppSshFeaturePresenter.new(app),
Presenters::V3::AppRevisionsFeaturePresenter.new(app)
Presenters::V3::AppRevisionsFeaturePresenter.new(app),
Presenters::V3::AppFileBasedServiceBindingsFeaturePresenter.new(app)
]
end
end
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
require 'presenters/v3/base_presenter'

module VCAP::CloudController::Presenters::V3
class AppFileBasedServiceBindingsFeaturePresenter < BasePresenter
def to_hash
{
name: 'file-based-service-bindings',
description: 'Enable file-based service bindings for the app',
enabled: app.file_based_service_bindings_enabled
}
end

private

def app
@resource
end
end
end
7 changes: 6 additions & 1 deletion docs/v3/source/includes/api_resources/_app_features.erb
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,15 @@
"name": "revisions",
"description": "Enable versioning of an application",
"enabled": false
},
{
"name": "file-based-service-bindings",
"description": "Enable file-based service bindings for the app",
"enabled": false
}
],
"pagination": {
"total_results": 1,
"total_results": 3,
"total_pages": 1,
"first": { "href": "/v3/apps/05d39de4-2c9e-4c76-8fd6-10417da07e42/features" },
"last": { "href": "/v3/apps/05d39de4-2c9e-4c76-8fd6-10417da07e42/features" },
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,4 @@ Name | Description
---- | -----------
**ssh** | Enable SSHing into the app
**revisions** | Enable [versioning](#revisions) of an application
**file-based-service-bindings** | Enable file-based service bindings for the app (experimental)
56 changes: 54 additions & 2 deletions spec/request/app_features_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
let(:admin_header) { admin_headers_for(user) }
let(:org) { VCAP::CloudController::Organization.make(created_at: 3.days.ago) }
let(:space) { VCAP::CloudController::Space.make(organization: org) }
let(:app_model) { VCAP::CloudController::AppModel.make(space: space, enable_ssh: true) }
let(:app_model) { VCAP::CloudController::AppModel.make(space: space, enable_ssh: true, file_based_service_bindings_enabled: true) }

describe 'GET /v3/apps/:guid/features' do
context 'getting a list of available features for the app' do
Expand All @@ -24,11 +24,16 @@
'name' => 'revisions',
'description' => 'Enable versioning of an application',
'enabled' => true
},
{
'name' => 'file-based-service-bindings',
'description' => 'Enable file-based service bindings for the app',
'enabled' => true
}
],
'pagination' =>
{
'total_results' => 2,
'total_results' => 3,
'total_pages' => 1,
'first' => { 'href' => "/v3/apps/#{app_model.guid}/features" },
'last' => { 'href' => "/v3/apps/#{app_model.guid}/features" },
Expand Down Expand Up @@ -94,6 +99,19 @@

it_behaves_like 'permissions for single object endpoint', ALL_PERMISSIONS
end

context 'file-based-service-bindings app feature' do
let(:api_call) { ->(user_headers) { get "/v3/apps/#{app_model.guid}/features/file-based-service-bindings", nil, user_headers } }
let(:feature_response_object) do
{
'name' => 'file-based-service-bindings',
'description' => 'Enable file-based service bindings for the app',
'enabled' => true
}
end

it_behaves_like 'permissions for single object endpoint', ALL_PERMISSIONS
end
end

describe 'PATCH /v3/apps/:guid/features/:name' do
Expand Down Expand Up @@ -172,5 +190,39 @@
it_behaves_like 'permissions for single object endpoint', ALL_PERMISSIONS
end
end

context 'file-based-service-bindings app feature' do
let(:api_call) { ->(user_headers) { patch "/v3/apps/#{app_model.guid}/features/file-based-service-bindings", request_body.to_json, user_headers } }
let(:feature_response_object) do
{
'name' => 'file-based-service-bindings',
'description' => 'Enable file-based service bindings for the app',
'enabled' => false
}
end

let(:expected_codes_and_responses) do
h = Hash.new(code: 403, errors: CF_NOT_AUTHORIZED)
%w[no_role org_auditor org_billing_manager].each { |r| h[r] = { code: 404 } }
%w[admin space_developer].each { |r| h[r] = { code: 200, response_object: feature_response_object } }
h
end

it_behaves_like 'permissions for single object endpoint', ALL_PERMISSIONS

context 'when organization is suspended' do
let(:expected_codes_and_responses) do
h = super()
h['space_developer'] = { code: 403, errors: CF_ORG_SUSPENDED }
h
end

before do
org.update(status: VCAP::CloudController::Organization::SUSPENDED)
end

it_behaves_like 'permissions for single object endpoint', ALL_PERMISSIONS
end
end
end
end
10 changes: 9 additions & 1 deletion spec/unit/actions/app_feature_update_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
module VCAP::CloudController
RSpec.describe AppFeatureUpdate do
subject(:app_feature_update) { AppFeatureUpdate }
let(:app) { AppModel.make(enable_ssh: false, revisions_enabled: false) }
let(:app) { AppModel.make(enable_ssh: false, revisions_enabled: false, file_based_service_bindings_enabled: false) }
let(:message) { AppFeatureUpdateMessage.new(enabled: true) }

describe '.update' do
Expand All @@ -24,6 +24,14 @@ module VCAP::CloudController
end.to change { app.reload.revisions_enabled }.to(true)
end
end

context 'when the feature name is file-based-service-bindings' do
it 'updates the file_based_service_bindings_enabled column on the app' do
expect do
AppFeatureUpdate.update('file-based-service-bindings', app, message)
end.to change { app.reload.file_based_service_bindings_enabled }.to(true)
end
end
end
end
end
14 changes: 11 additions & 3 deletions spec/unit/controllers/v3/app_features_controller_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,15 @@
## NOTICE: Prefer request specs over controller specs as per ADR #0003 ##

RSpec.describe AppFeaturesController, type: :controller do
let(:app_model) { VCAP::CloudController::AppModel.make(enable_ssh: true) }
let(:app_model) { VCAP::CloudController::AppModel.make(enable_ssh: true, file_based_service_bindings_enabled: true) }
let(:space) { app_model.space }
let(:org) { space.organization }
let(:user) { VCAP::CloudController::User.make }
let(:app_feature_ssh_response) { { 'name' => 'ssh', 'description' => 'Enable SSHing into the app.', 'enabled' => true } }
let(:app_feature_revisions_response) { { 'name' => 'revisions', 'description' => 'Enable versioning of an application', 'enabled' => true } }
let(:app_feature_file_based_service_bindings_response) do
{ 'name' => 'file-based-service-bindings', 'description' => 'Enable file-based service bindings for the app', 'enabled' => true }
end

before do
space.update(allow_ssh: true)
Expand All @@ -20,7 +23,7 @@
describe '#index' do
let(:pagination_hash) do
{
'total_results' => 2,
'total_results' => 3,
'total_pages' => 1,
'first' => { 'href' => "/v3/apps/#{app_model.guid}/features" },
'last' => { 'href' => "/v3/apps/#{app_model.guid}/features" },
Expand All @@ -39,7 +42,7 @@
it 'returns app features' do
get :index, params: { app_guid: app_model.guid }
expect(parsed_body).to eq(
'resources' => [app_feature_ssh_response, app_feature_revisions_response],
'resources' => [app_feature_ssh_response, app_feature_revisions_response, app_feature_file_based_service_bindings_response],
'pagination' => pagination_hash
)
end
Expand Down Expand Up @@ -67,6 +70,11 @@
expect(parsed_body).to eq(app_feature_revisions_response)
end

it 'returns the file-based-service-bindings app feature' do
get :show, params: { app_guid: app_model.guid, name: 'file-based-service-bindings' }
expect(parsed_body).to eq(app_feature_file_based_service_bindings_response)
end

it 'throws 404 for a non-existent feature' do
set_current_user_as_role(role: 'admin', org: org, space: space, user: user)

Expand Down
14 changes: 14 additions & 0 deletions spec/unit/presenters/v3/app_feature_presenter_spec.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
require 'spec_helper'
require 'presenters/v3/app_ssh_feature_presenter'
require 'presenters/v3/app_file_based_service_bindings_feature_presenter'

module VCAP::CloudController::Presenters::V3
RSpec.describe AppSshFeaturePresenter do
Expand All @@ -14,4 +15,17 @@ module VCAP::CloudController::Presenters::V3
end
end
end

RSpec.describe AppFileBasedServiceBindingsFeaturePresenter do
let(:app) { VCAP::CloudController::AppModel.make }

describe '#to_hash' do
it 'presents the app feature as json' do
result = AppFileBasedServiceBindingsFeaturePresenter.new(app).to_hash
expect(result[:name]).to eq('file-based-service-bindings')
expect(result[:description]).to eq('Enable file-based service bindings for the app')
expect(result[:enabled]).to eq(app.file_based_service_bindings_enabled)
end
end
end
end

0 comments on commit 3e7021d

Please sign in to comment.