Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
5 changes: 3 additions & 2 deletions app/models/runtime/route.rb
Original file line number Diff line number Diff line change
Expand Up @@ -74,8 +74,9 @@ def options_with_serialization=(opts)
cleaned_opts = remove_hash_options_for_non_hash_loadbalancing(opts)
rounded_opts = round_hash_balance_to_one_decimal(cleaned_opts)
normalized_opts = normalize_hash_balance_to_string(rounded_opts)
# Remove nil values after all processing
normalized_opts = normalized_opts.compact if normalized_opts.is_a?(Hash)
# Convert nil values to empty strings to signal explicit removal to downstream consumers (e.g. gorouter),
# so they can distinguish "option was explicitly removed" from "option was never set".
normalized_opts = normalized_opts.transform_values { |v| v.nil? ? '' : v } if normalized_opts.is_a?(Hash)
self.options_without_serialization = Oj.dump(normalized_opts)
end

Expand Down
3 changes: 1 addition & 2 deletions spec/unit/actions/manifest_route_update_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -650,8 +650,7 @@ module VCAP::CloudController
ManifestRouteUpdate.update(app.guid, message, user_audit_info)

route.reload
expect(route.options).to eq({})
expect(route.options).not_to have_key('loadbalancing')
expect(route.options).to eq({ 'loadbalancing' => '' })
expect(route.options).not_to have_key('hash_header')
expect(route.options).not_to have_key('hash_balance')
end
Expand Down
6 changes: 3 additions & 3 deletions spec/unit/actions/route_update_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -209,7 +209,7 @@ module VCAP::CloudController
expect(message).to be_valid
subject.update(route:, message:)
route.reload
expect(route.options).to eq({})
expect(route.options).to eq({ 'loadbalancing' => '' })
end

it 'notifies the backend' do
Expand Down Expand Up @@ -299,7 +299,7 @@ module VCAP::CloudController
subject.update(route:, message:)
route.reload
expect(route.options).to include({ 'loadbalancing' => 'hash', 'hash_header' => 'foobar' })
expect(route.options).not_to have_key('hash_balance')
expect(route.options['hash_balance']).to eq('')
end

it 'notifies the backend' do
Expand Down Expand Up @@ -502,7 +502,7 @@ module VCAP::CloudController
expect(message).to be_valid
subject.update(route:, message:)
route.reload
expect(route.options).to eq({})
expect(route.options).to eq({ 'loadbalancing' => '' })
end

it 'notifies the backend' do
Expand Down
17 changes: 17 additions & 0 deletions spec/unit/models/runtime/route_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -1346,6 +1346,23 @@ module VCAP::CloudController
end
end

context 'when setting an option value to nil' do
it 'serializes nil values as empty strings to signal explicit removal' do
route = Route.make(
host: 'test-route',
domain: domain,
space: space,
options: { loadbalancing: 'round-robin' }
)

route.update(options: { loadbalancing: nil })
route.reload

parsed_options = Oj.load(route.options_without_serialization)
expect(parsed_options['loadbalancing']).to eq('')
end
end

context 'when using string keys instead of symbols' do
it 'still removes hash options for non-hash loadbalancing' do
route = Route.make(
Expand Down
Loading