Skip to content
This repository was archived by the owner on Jun 2, 2021. It is now read-only.

Commit 3ec790f

Browse files
committed
**V3**: create-route can now take in a port for tcp domains
- add kubernetes check when checking for tcp in domains - use actions/route_create and delete actions/v3/route_create - refactored protocols method on domain Co-authored-by: Sarah Weinstein <sweinstein@pivotal.io> [#162107369]
1 parent 9ac9b0c commit 3ec790f

20 files changed

Lines changed: 552 additions & 235 deletions

app/actions/manifest_route_update.rb

Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
require 'cloud_controller/app_manifest/manifest_route'
2-
require 'actions/v3/route_create'
2+
require 'actions/route_create'
33

44
module VCAP::CloudController
55
class ManifestRouteUpdate
@@ -40,15 +40,13 @@ def update(app_guid, message, user_audit_info)
4040
manifest_triggered: true
4141
)
4242
end
43-
rescue Sequel::ValidationFailed => e
43+
rescue Sequel::ValidationFailed, RouteCreate::Error => e
4444
raise InvalidRoute.new(e.message)
4545
end
4646

4747
private
4848

4949
def find_or_create_valid_route(app, manifest_route, user_audit_info)
50-
logger = Steno.logger('cc.action.route_update')
51-
5250
manifest_route[:candidate_host_domain_pairs].each do |candidate|
5351
potential_domain = candidate[:domain]
5452
existing_domain = Domain.find(name: potential_domain)
@@ -71,14 +69,18 @@ def find_or_create_valid_route(app, manifest_route, user_audit_info)
7169
raise CloudController::Errors::ApiError.new_from_details('NotAuthorized')
7270
end
7371

74-
route_hash = {
75-
host: host,
76-
domain_guid: existing_domain.guid,
77-
path: manifest_route[:path],
78-
port: manifest_route[:port] || 0,
79-
space_guid: app.space.guid
80-
}
81-
route = V3::RouteCreate.create_route(route_hash: route_hash, user_audit_info: user_audit_info, logger: logger, manifest_triggered: true)
72+
message = RouteCreateMessage.new({
73+
'host' => host,
74+
'path' => manifest_route[:path],
75+
'port' => manifest_route[:port],
76+
})
77+
78+
route = RouteCreate.new(user_audit_info).create(
79+
message: message,
80+
space: app.space,
81+
domain: existing_domain,
82+
manifest_triggered: true,
83+
)
8284
elsif route.space.guid != app.space.guid
8385
raise InvalidRoute.new('Routes cannot be mapped to destinations in different spaces')
8486
end

app/actions/route_create.rb

Lines changed: 44 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,11 @@ def initialize(user_audit_info)
77
@user_audit_info = user_audit_info
88
end
99

10-
def create(message:, space:, domain:)
10+
def create(message:, space:, domain:, manifest_triggered: false)
1111
route = Route.new(
1212
host: message.host || '',
1313
path: message.path || '',
14+
port: message.port || 0,
1415
space: space,
1516
domain: domain,
1617
)
@@ -25,7 +26,7 @@ def create(message:, space:, domain:)
2526
route,
2627
@user_audit_info,
2728
message.audit_hash,
28-
manifest_triggered: false,
29+
manifest_triggered: manifest_triggered,
2930
)
3031

3132
if VCAP::CloudController::Config.kubernetes_api_configured?
@@ -34,7 +35,7 @@ def create(message:, space:, domain:)
3435

3536
route
3637
rescue Sequel::ValidationFailed => e
37-
validation_error!(e, route.host, route.path, space, domain)
38+
validation_error!(e, route.host, route.path, route.port, space, domain)
3839
end
3940

4041
private
@@ -43,7 +44,7 @@ def route_crd_client
4344
@route_crd_client ||= CloudController::DependencyLocator.instance.route_crd_client
4445
end
4546

46-
def validation_error!(error, host, path, space, domain)
47+
def validation_error!(error, host, path, port, space, domain)
4748
if error.errors.on(:domain)&.include?(:invalid_relation)
4849
error!("Invalid domain. Domain '#{domain.name}' is not available in organization '#{space.organization.name}'.")
4950
end
@@ -52,12 +53,21 @@ def validation_error!(error, host, path, space, domain)
5253
error!("Routes quota exceeded for space '#{space.name}'.")
5354
end
5455

56+
if error.errors.on(:space)&.include?(:total_reserved_route_ports_exceeded)
57+
error!("Reserved route ports quota exceeded for space '#{space.name}'.")
58+
end
59+
5560
if error.errors.on(:organization)&.include?(:total_routes_exceeded)
5661
error!("Routes quota exceeded for organization '#{space.organization.name}'.")
5762
end
5863

64+
if error.errors.on(:organization)&.include?(:total_reserved_route_ports_exceeded)
65+
error!("Reserved route ports quota exceeded for organization '#{space.organization.name}'.")
66+
end
67+
5968
validation_error_host!(error, host, domain)
6069
validation_error_path!(error, host, path, domain)
70+
validation_error_port!(error, host, port, domain)
6171

6272
error!(error.message)
6373
end
@@ -71,6 +81,10 @@ def validation_error_host!(error, host, domain)
7181
error!('Route conflicts with a reserved system route.')
7282
end
7383

84+
if error.errors.on(:host)&.include?(:format)
85+
error!('Host format is invalid.')
86+
end
87+
7488
if error.errors.on(:host)&.include?(:wildcard_host_not_supported_for_internal_domain)
7589
error!('Wildcard hosts are not supported for internal domains.')
7690
end
@@ -90,6 +104,10 @@ def validation_error_host!(error, host, domain)
90104
error!("Route already exists with host '#{host}' for domain '#{domain.name}'.")
91105
end
92106
end
107+
108+
if error.errors.on(:host)&.include?(:host_and_path_domain_tcp)
109+
error!("Routes with protocol 'tcp' do not support paths or hosts.")
110+
end
93111
end
94112

95113
def validation_error_path!(error, host, path, domain)
@@ -125,6 +143,28 @@ def validation_error_path!(error, host, path, domain)
125143
end
126144
end
127145

146+
def validation_error_port!(error, host, port, domain)
147+
if error.errors.on(:port)&.include?(:port_required)
148+
error!("Routes with protocol 'tcp' must specify a port.")
149+
end
150+
151+
if error.errors.on(:port)&.include?(:port_unavailable)
152+
error!("Port '#{port}' is not available. Try a different port or use a different domain.")
153+
end
154+
155+
if error.errors.on([:host, :domain_id, :port])&.include?(:unique)
156+
error!("Route already exists with port '#{port}' for domain '#{domain.name}'.")
157+
end
158+
159+
if error.errors.on(:port)&.include?(:port_taken)
160+
error!("Port '#{port}' is not available. Try a different port or use a different domain.")
161+
end
162+
163+
if error.errors.on(:port)&.include?(:port_unsupported)
164+
error!("Routes with protocol 'http' do not support ports.")
165+
end
166+
end
167+
128168
def error!(message)
129169
raise Error.new(message)
130170
end

app/actions/v3/route_create.rb

Lines changed: 0 additions & 23 deletions
This file was deleted.

app/messages/route_create_message.rb

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ class RouteCreateMessage < MetadataBaseMessage
88
register_allowed_keys [
99
:host,
1010
:path,
11+
:port,
1112
:relationships
1213
]
1314

@@ -47,6 +48,10 @@ class RouteCreateMessage < MetadataBaseMessage
4748
message: 'cannot be exactly /',
4849
}
4950

51+
validates :port,
52+
allow_nil: true,
53+
numericality: { only_integer: true, greater_than_or_equal_to: 0, less_than_or_equal_to: 65535 }
54+
5055
validates :relationships, presence: true
5156

5257
validates_with NoAdditionalKeysValidator

app/models/runtime/domain.rb

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -144,17 +144,15 @@ def in_suspended_org?
144144
end
145145

146146
def protocols
147-
return ['http'] if self.private?
148-
149-
# If Kubernetes is enabled that implies that we are using istio, not the routing API
150-
k8s_enabled = Config.config.get(:kubernetes, :host_url).present?
151-
return ['tcp'] if !k8s_enabled && self.router_group_guid
152-
153147
['http']
154148
end
155149

156150
private
157151

152+
def k8s_enabled?
153+
Config.config.get(:kubernetes, :host_url).present?
154+
end
155+
158156
def validate_change_owning_organization(organization)
159157
return if self.new? || owning_organization == organization
160158

app/models/runtime/shared_domain.rb

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,16 @@ def shared?
6060
true
6161
end
6262

63+
def protocols
64+
return ['tcp'] if self.tcp?
65+
66+
['http']
67+
end
68+
6369
def tcp?
70+
# If Kubernetes is enabled that implies that we are using istio, not the routing API
71+
return false if k8s_enabled?
72+
6473
if router_group_guid.present?
6574
if @router_group_type.nil?
6675
router_group = routing_api_client.router_group(router_group_guid)

app/presenters/v3/route_presenter.rb

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ def to_hash
3131
updated_at: route.updated_at,
3232
host: route.host,
3333
path: route.path,
34+
port: route.port,
3435
url: build_url,
3536
destinations: route.route_mappings.map { |rm| RouteDestinationPresenter.new(rm).to_hash },
3637
metadata: {
@@ -80,6 +81,10 @@ def build_links
8081
end
8182

8283
def build_url
84+
if route.port && route.port > 0
85+
return "#{route.domain.name}:#{route.port}"
86+
end
87+
8388
if route.host.empty?
8489
return "#{route.domain.name}#{route.path}"
8590
end

0 commit comments

Comments
 (0)