Skip to content

Commit 388c2f8

Browse files
authored
[RFC0030 - 3] Rename 'file-based-service-bindings' to 'service-binding-k8s' and introduce 'file-based-vcap-services' (#4235)
* Add column 'service_binding_k8s_enabled' to apps table * Rename 'file-based-service-bindings' feature to 'service-binding-k8s' * Introduce 'file-based-vcap-services' app feature * Improve migration and add migration tests * Fix migration tests for mysql * Do not try to create/drop check constraint on mysql < 8 * Use constants for app feature names
1 parent 66df34c commit 388c2f8

13 files changed

+579
-78
lines changed

app/actions/app_feature_update.rb

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,14 @@ module VCAP::CloudController
22
class AppFeatureUpdate
33
def self.update(feature_name, app, message)
44
case feature_name
5-
when 'ssh'
5+
when AppFeaturesController::SSH_FEATURE
66
app.update(enable_ssh: message.enabled)
7-
when 'revisions'
7+
when AppFeaturesController::REVISIONS_FEATURE
88
app.update(revisions_enabled: message.enabled)
9-
when 'file-based-service-bindings'
10-
app.update(file_based_service_bindings_enabled: message.enabled)
9+
when AppFeaturesController::SERVICE_BINDING_K8S_FEATURE
10+
app.update(service_binding_k8s_enabled: message.enabled)
11+
when AppFeaturesController::FILE_BASED_VCAP_SERVICES_FEATURE
12+
app.update(file_based_vcap_services_enabled: message.enabled)
1113
end
1214
end
1315
end

app/controllers/v3/app_features_controller.rb

Lines changed: 21 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,8 @@
22
require 'controllers/v3/mixins/app_sub_resource'
33
require 'presenters/v3/app_ssh_feature_presenter'
44
require 'presenters/v3/app_revisions_feature_presenter'
5-
require 'presenters/v3/app_file_based_service_bindings_feature_presenter'
5+
require 'presenters/v3/app_service_binding_k8s_feature_presenter'
6+
require 'presenters/v3/app_file_based_vcap_services_feature_presenter'
67
require 'presenters/v3/app_ssh_status_presenter'
78
require 'actions/app_feature_update'
89

@@ -11,9 +12,10 @@ class AppFeaturesController < ApplicationController
1112

1213
SSH_FEATURE = 'ssh'.freeze
1314
REVISIONS_FEATURE = 'revisions'.freeze
14-
FILE_BASED_SERVICE_BINDINGS_FEATURE = 'file-based-service-bindings'.freeze
15+
SERVICE_BINDING_K8S_FEATURE = 'service-binding-k8s'.freeze
16+
FILE_BASED_VCAP_SERVICES_FEATURE = 'file-based-vcap-services'.freeze
1517

16-
TRUSTED_APP_FEATURES = [SSH_FEATURE, FILE_BASED_SERVICE_BINDINGS_FEATURE].freeze
18+
TRUSTED_APP_FEATURES = [SSH_FEATURE, SERVICE_BINDING_K8S_FEATURE, FILE_BASED_VCAP_SERVICES_FEATURE].freeze
1719
UNTRUSTED_APP_FEATURES = [REVISIONS_FEATURE].freeze
1820
APP_FEATURES = (TRUSTED_APP_FEATURES + UNTRUSTED_APP_FEATURES).freeze
1921

@@ -53,6 +55,10 @@ def update
5355
message = VCAP::CloudController::AppFeatureUpdateMessage.new(hashed_params['body'])
5456
unprocessable!(message.errors.full_messages) unless message.valid?
5557

58+
if message.enabled && both_service_binding_features_enabled?(app, name)
59+
unprocessable!("'#{FILE_BASED_VCAP_SERVICES_FEATURE}' and '#{SERVICE_BINDING_K8S_FEATURE}' features cannot be enabled at the same time.")
60+
end
61+
5662
AppFeatureUpdate.update(hashed_params[:name], app, message)
5763
render status: :ok, json: feature_presenter_for(hashed_params[:name], app)
5864
end
@@ -83,7 +89,8 @@ def feature_presenter_for(feature_name, app)
8389
presenters = {
8490
SSH_FEATURE => Presenters::V3::AppSshFeaturePresenter,
8591
REVISIONS_FEATURE => Presenters::V3::AppRevisionsFeaturePresenter,
86-
FILE_BASED_SERVICE_BINDINGS_FEATURE => Presenters::V3::AppFileBasedServiceBindingsFeaturePresenter
92+
SERVICE_BINDING_K8S_FEATURE => Presenters::V3::AppServiceBindingK8sFeaturePresenter,
93+
FILE_BASED_VCAP_SERVICES_FEATURE => Presenters::V3::AppFileBasedVcapServicesFeaturePresenter
8794
}
8895
presenters[feature_name].new(app)
8996
end
@@ -92,7 +99,16 @@ def presented_app_features(app)
9299
[
93100
Presenters::V3::AppSshFeaturePresenter.new(app),
94101
Presenters::V3::AppRevisionsFeaturePresenter.new(app),
95-
Presenters::V3::AppFileBasedServiceBindingsFeaturePresenter.new(app)
102+
Presenters::V3::AppServiceBindingK8sFeaturePresenter.new(app),
103+
Presenters::V3::AppFileBasedVcapServicesFeaturePresenter.new(app)
96104
]
97105
end
106+
107+
def both_service_binding_features_enabled?(app, feature_name)
108+
if feature_name == FILE_BASED_VCAP_SERVICES_FEATURE
109+
app.service_binding_k8s_enabled
110+
elsif feature_name == SERVICE_BINDING_K8S_FEATURE
111+
app.file_based_vcap_services_enabled
112+
end
113+
end
98114
end

app/presenters/v3/app_file_based_service_bindings_feature_presenter.rb

Lines changed: 0 additions & 19 deletions
This file was deleted.
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
require 'presenters/v3/base_presenter'
2+
3+
module VCAP::CloudController::Presenters::V3
4+
class AppFileBasedVcapServicesFeaturePresenter < BasePresenter
5+
def to_hash
6+
{
7+
name: AppFeaturesController::FILE_BASED_VCAP_SERVICES_FEATURE,
8+
description: 'Enable file-based VCAP service bindings for the app',
9+
enabled: app.file_based_vcap_services_enabled
10+
}
11+
end
12+
13+
private
14+
15+
def app
16+
@resource
17+
end
18+
end
19+
end
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
require 'presenters/v3/base_presenter'
2+
3+
module VCAP::CloudController::Presenters::V3
4+
class AppServiceBindingK8sFeaturePresenter < BasePresenter
5+
def to_hash
6+
{
7+
name: AppFeaturesController::SERVICE_BINDING_K8S_FEATURE,
8+
description: 'Enable k8s service bindings for the app',
9+
enabled: app.service_binding_k8s_enabled
10+
}
11+
end
12+
13+
private
14+
15+
def app
16+
@resource
17+
end
18+
end
19+
end
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
Sequel.migration do
2+
up do
3+
if database_type == :postgres
4+
alter_table :apps do
5+
add_column :service_binding_k8s_enabled, :boolean, default: false, null: false, if_not_exists: true
6+
add_column :file_based_vcap_services_enabled, :boolean, default: false, null: false, if_not_exists: true
7+
8+
unless check_constraint_exists?(@db)
9+
add_constraint(name: :only_one_sb_feature_enabled, if_not_exists: true) do
10+
Sequel.lit('NOT (service_binding_k8s_enabled AND file_based_vcap_services_enabled)')
11+
end
12+
end
13+
end
14+
15+
elsif database_type == :mysql
16+
add_column :apps, :service_binding_k8s_enabled, :boolean, default: false, null: false unless schema(:apps).map(&:first).include?(:service_binding_k8s_enabled)
17+
add_column :apps, :file_based_vcap_services_enabled, :boolean, default: false, null: false unless schema(:apps).map(&:first).include?(:file_based_vcap_services_enabled)
18+
19+
if check_constraint_supported?(self) && !check_constraint_exists?(self)
20+
run('ALTER TABLE apps ADD CONSTRAINT only_one_sb_feature_enabled CHECK (NOT (service_binding_k8s_enabled AND file_based_vcap_services_enabled))')
21+
end
22+
end
23+
end
24+
25+
down do
26+
alter_table :apps do
27+
drop_constraint :only_one_sb_feature_enabled if check_constraint_supported?(@db) && check_constraint_exists?(@db)
28+
drop_column :service_binding_k8s_enabled if @db.schema(:apps).map(&:first).include?(:service_binding_k8s_enabled)
29+
drop_column :file_based_vcap_services_enabled if @db.schema(:apps).map(&:first).include?(:file_based_vcap_services_enabled)
30+
end
31+
end
32+
end
33+
34+
def check_constraint_exists?(database)
35+
if database.database_type == :postgres
36+
database.check_constraints(:apps).include?(:only_one_sb_feature_enabled)
37+
elsif database.database_type == :mysql
38+
database[:information_schema__table_constraints].where(TABLE_SCHEMA: database.opts[:database], TABLE_NAME: 'apps', CONSTRAINT_TYPE: 'CHECK',
39+
CONSTRAINT_NAME: 'only_one_sb_feature_enabled').any?
40+
end
41+
end
42+
43+
# check constraints are not available in Mysql versions < 8
44+
# this is also enforced on application level, so it should be fine not to create it on that version
45+
def check_constraint_supported?(database)
46+
database.database_type == :postgres || (database.database_type == :mysql && database.server_version >= 80_000)
47+
end

docs/v3/source/includes/api_resources/_app_features.erb

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,13 +20,18 @@
2020
"enabled": false
2121
},
2222
{
23-
"name": "file-based-service-bindings",
24-
"description": "Enable file-based service bindings for the app",
23+
"name": "service-binding-k8s",
24+
"description": "Enable k8s service bindings for the app",
25+
"enabled": false
26+
},
27+
{
28+
"name": "file-based-vcap-services",
29+
"description": "Enable file-based VCAP service bindings for the app",
2530
"enabled": false
2631
}
2732
],
2833
"pagination": {
29-
"total_results": 3,
34+
"total_results": 4,
3035
"total_pages": 1,
3136
"first": { "href": "/v3/apps/05d39de4-2c9e-4c76-8fd6-10417da07e42/features" },
3237
"last": { "href": "/v3/apps/05d39de4-2c9e-4c76-8fd6-10417da07e42/features" },

docs/v3/source/includes/resources/app_features/_supported_features.md.erb

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,4 +6,5 @@ Name | Description
66
---- | -----------
77
**ssh** | Enable SSHing into the app
88
**revisions** | Enable [versioning](#revisions) of an application
9-
**file-based-service-bindings** | Enable file-based service bindings for the app (experimental)
9+
**service-binding-k8s** | Enable k8s service bindings for the app (experimental)
10+
**file-based-vcap-services** | Enable file-based VCAP service bindings for the app (experimental)

0 commit comments

Comments
 (0)