Skip to content

Commit d825336

Browse files
committed
Add feature flags to v1 app manifests (read-only)
- introduce AppFeatures helper containing constants and the mapping to database columns - add FeaturesPresenter - wire into AppManifestPresenter - update request and unit tests for new 'features' hash
1 parent 0a8b92a commit d825336

File tree

12 files changed

+104
-28
lines changed

12 files changed

+104
-28
lines changed

app/actions/app_feature_update.rb

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,13 @@ module VCAP::CloudController
22
class AppFeatureUpdate
33
def self.update(feature_name, app, message)
44
case feature_name
5-
when AppFeaturesController::SSH_FEATURE
5+
when AppFeatures::SSH_FEATURE
66
app.update(enable_ssh: message.enabled)
7-
when AppFeaturesController::REVISIONS_FEATURE
7+
when AppFeatures::REVISIONS_FEATURE
88
app.update(revisions_enabled: message.enabled)
9-
when AppFeaturesController::SERVICE_BINDING_K8S_FEATURE
9+
when AppFeatures::SERVICE_BINDING_K8S_FEATURE
1010
app.update(service_binding_k8s_enabled: message.enabled)
11-
when AppFeaturesController::FILE_BASED_VCAP_SERVICES_FEATURE
11+
when AppFeatures::FILE_BASED_VCAP_SERVICES_FEATURE
1212
app.update(file_based_vcap_services_enabled: message.enabled)
1313
end
1414
end

app/controllers/v3/app_features_controller.rb

Lines changed: 14 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -6,17 +6,14 @@
66
require 'presenters/v3/app_file_based_vcap_services_feature_presenter'
77
require 'presenters/v3/app_ssh_status_presenter'
88
require 'actions/app_feature_update'
9+
require 'models/helpers/app_features'
910

1011
class AppFeaturesController < ApplicationController
1112
include AppSubResource
1213

13-
SSH_FEATURE = 'ssh'.freeze
14-
REVISIONS_FEATURE = 'revisions'.freeze
15-
SERVICE_BINDING_K8S_FEATURE = 'service-binding-k8s'.freeze
16-
FILE_BASED_VCAP_SERVICES_FEATURE = 'file-based-vcap-services'.freeze
17-
18-
TRUSTED_APP_FEATURES = [SSH_FEATURE, SERVICE_BINDING_K8S_FEATURE, FILE_BASED_VCAP_SERVICES_FEATURE].freeze
19-
UNTRUSTED_APP_FEATURES = [REVISIONS_FEATURE].freeze
14+
TRUSTED_APP_FEATURES = [VCAP::CloudController::AppFeatures::SSH_FEATURE, VCAP::CloudController::AppFeatures::SERVICE_BINDING_K8S_FEATURE,
15+
VCAP::CloudController::AppFeatures::FILE_BASED_VCAP_SERVICES_FEATURE].freeze
16+
UNTRUSTED_APP_FEATURES = [VCAP::CloudController::AppFeatures::REVISIONS_FEATURE].freeze
2017
APP_FEATURES = (TRUSTED_APP_FEATURES + UNTRUSTED_APP_FEATURES).freeze
2118

2219
def index
@@ -56,11 +53,12 @@ def update
5653
unprocessable!(message.errors.full_messages) unless message.valid?
5754

5855
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.")
56+
unprocessable!("'#{VCAP::CloudController::AppFeatures::FILE_BASED_VCAP_SERVICES_FEATURE}' and '#{VCAP::CloudController::AppFeatures::SERVICE_BINDING_K8S_FEATURE}' " \
57+
'features cannot be enabled at the same time.')
6058
end
6159

62-
AppFeatureUpdate.update(hashed_params[:name], app, message)
63-
render status: :ok, json: feature_presenter_for(hashed_params[:name], app)
60+
AppFeatureUpdate.update(name, app, message)
61+
render status: :ok, json: feature_presenter_for(name, app)
6462
end
6563

6664
def ssh_enabled
@@ -87,10 +85,10 @@ def present_unpagination_hash(result, path)
8785

8886
def feature_presenter_for(feature_name, app)
8987
presenters = {
90-
SSH_FEATURE => Presenters::V3::AppSshFeaturePresenter,
91-
REVISIONS_FEATURE => Presenters::V3::AppRevisionsFeaturePresenter,
92-
SERVICE_BINDING_K8S_FEATURE => Presenters::V3::AppServiceBindingK8sFeaturePresenter,
93-
FILE_BASED_VCAP_SERVICES_FEATURE => Presenters::V3::AppFileBasedVcapServicesFeaturePresenter
88+
VCAP::CloudController::AppFeatures::SSH_FEATURE => Presenters::V3::AppSshFeaturePresenter,
89+
VCAP::CloudController::AppFeatures::REVISIONS_FEATURE => Presenters::V3::AppRevisionsFeaturePresenter,
90+
VCAP::CloudController::AppFeatures::SERVICE_BINDING_K8S_FEATURE => Presenters::V3::AppServiceBindingK8sFeaturePresenter,
91+
VCAP::CloudController::AppFeatures::FILE_BASED_VCAP_SERVICES_FEATURE => Presenters::V3::AppFileBasedVcapServicesFeaturePresenter
9492
}
9593
presenters[feature_name].new(app)
9694
end
@@ -105,9 +103,9 @@ def presented_app_features(app)
105103
end
106104

107105
def both_service_binding_features_enabled?(app, feature_name)
108-
if feature_name == FILE_BASED_VCAP_SERVICES_FEATURE
106+
if feature_name == VCAP::CloudController::AppFeatures::FILE_BASED_VCAP_SERVICES_FEATURE
109107
app.service_binding_k8s_enabled
110-
elsif feature_name == SERVICE_BINDING_K8S_FEATURE
108+
elsif feature_name == VCAP::CloudController::AppFeatures::SERVICE_BINDING_K8S_FEATURE
111109
app.file_based_vcap_services_enabled
112110
end
113111
end

app/models/helpers/app_features.rb

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
module VCAP::CloudController
2+
class AppFeatures
3+
SSH_FEATURE = 'ssh'.freeze
4+
REVISIONS_FEATURE = 'revisions'.freeze
5+
SERVICE_BINDING_K8S_FEATURE = 'service-binding-k8s'.freeze
6+
FILE_BASED_VCAP_SERVICES_FEATURE = 'file-based-vcap-services'.freeze
7+
8+
DATABASE_COLUMNS_MAPPING = {
9+
SSH_FEATURE => :enable_ssh,
10+
REVISIONS_FEATURE => :revisions_enabled,
11+
SERVICE_BINDING_K8S_FEATURE => :service_binding_k8s_enabled,
12+
FILE_BASED_VCAP_SERVICES_FEATURE => :file_based_vcap_services_enabled
13+
}.freeze
14+
15+
def self.all_features
16+
[SSH_FEATURE, REVISIONS_FEATURE, SERVICE_BINDING_K8S_FEATURE, FILE_BASED_VCAP_SERVICES_FEATURE]
17+
end
18+
end
19+
end

app/presenters/v3/app_file_based_vcap_services_feature_presenter.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ module VCAP::CloudController::Presenters::V3
44
class AppFileBasedVcapServicesFeaturePresenter < BasePresenter
55
def to_hash
66
{
7-
name: AppFeaturesController::FILE_BASED_VCAP_SERVICES_FEATURE,
7+
name: VCAP::CloudController::AppFeatures::FILE_BASED_VCAP_SERVICES_FEATURE,
88
description: 'Enable file-based VCAP service bindings for the app',
99
enabled: app.file_based_vcap_services_enabled
1010
}

app/presenters/v3/app_manifest_presenter.rb

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
require 'presenters/v3/app_manifest_presenters/process_properties_presenter'
88
require 'presenters/v3/app_manifest_presenters/sidecar_properties_presenter'
99
require 'presenters/v3/app_manifest_presenters/lifecycle_presenter'
10+
require 'presenters/v3/app_manifest_presenters/features_presenter'
1011

1112
module VCAP::CloudController
1213
module Presenters
@@ -17,6 +18,7 @@ class AppManifestPresenter
1718
AppManifestPresenters::LifecyclePresenter.new,
1819
AppManifestPresenters::DockerPresenter.new,
1920
AppManifestPresenters::BuildpackPresenter.new,
21+
AppManifestPresenters::FeaturesPresenter.new,
2022
AppManifestPresenters::ServicesPropertiesPresenter.new,
2123
AppManifestPresenters::RoutePropertiesPresenter.new,
2224
AppManifestPresenters::MetadataPresenter.new,
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
module VCAP::CloudController
2+
module Presenters
3+
module V3
4+
module AppManifestPresenters
5+
class FeaturesPresenter
6+
def to_hash(app:, **_)
7+
features = {}
8+
AppFeatures.all_features.each do |feature|
9+
features[feature.to_sym] = app.send(AppFeatures::DATABASE_COLUMNS_MAPPING[feature])
10+
end
11+
12+
{
13+
features:
14+
}
15+
end
16+
end
17+
end
18+
end
19+
end
20+
end

app/presenters/v3/app_revisions_feature_presenter.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ module VCAP::CloudController::Presenters::V3
44
class AppRevisionsFeaturePresenter < BasePresenter
55
def to_hash
66
{
7-
name: 'revisions',
7+
name: VCAP::CloudController::AppFeatures::REVISIONS_FEATURE,
88
description: 'Enable versioning of an application',
99
enabled: app.revisions_enabled
1010
}

app/presenters/v3/app_service_binding_k8s_feature_presenter.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ module VCAP::CloudController::Presenters::V3
44
class AppServiceBindingK8sFeaturePresenter < BasePresenter
55
def to_hash
66
{
7-
name: AppFeaturesController::SERVICE_BINDING_K8S_FEATURE,
7+
name: VCAP::CloudController::AppFeatures::SERVICE_BINDING_K8S_FEATURE,
88
description: 'Enable k8s service bindings for the app',
99
enabled: app.service_binding_k8s_enabled
1010
}

app/presenters/v3/app_ssh_feature_presenter.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ module VCAP::CloudController::Presenters::V3
44
class AppSshFeaturePresenter < BasePresenter
55
def to_hash
66
{
7-
name: 'ssh',
7+
name: VCAP::CloudController::AppFeatures::SSH_FEATURE,
88
description: 'Enable SSHing into the app.',
99
enabled: app.enable_ssh
1010
}

spec/request/app_manifests_spec.rb

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,12 @@
9393
'lifecycle' => 'buildpack',
9494
'buildpacks' => [buildpack.name, buildpack2.name],
9595
'stack' => buildpack.stack,
96+
'features' => {
97+
'ssh' => true,
98+
'revisions' => true,
99+
'service-binding-k8s' => false,
100+
'file-based-vcap-services' => false
101+
},
96102
'services' => [service_binding.service_instance_name, service_binding2.service_instance_name],
97103
'routes' => [
98104
{
@@ -199,6 +205,12 @@
199205
'image' => docker_package.image,
200206
'username' => 'xXxMyL1ttlePwnyxXx'
201207
},
208+
'features' => {
209+
'ssh' => true,
210+
'revisions' => true,
211+
'service-binding-k8s' => false,
212+
'file-based-vcap-services' => false
213+
},
202214
'services' => [service_binding.service_instance_name, service_binding2.service_instance_name],
203215
'routes' => [
204216
{
@@ -274,6 +286,12 @@
274286
'name' => simple_app.name,
275287
'lifecycle' => 'buildpack',
276288
'stack' => 'itaewon_class_best_kdrama',
289+
'features' => {
290+
'ssh' => true,
291+
'revisions' => true,
292+
'service-binding-k8s' => false,
293+
'file-based-vcap-services' => false
294+
},
277295
'routes' => [
278296
{
279297
'route' => "#{route.host}.#{route.domain.name}",

0 commit comments

Comments
 (0)