Skip to content

Commit 52f1a38

Browse files
a18ehoffmaen
authored andcommitted
Adjust route options behaviour for manifest push
Overwrite behaviour for route options is now fixed and tested: Existing options are not modified if options is nil, {} or not provided A single option (e.g. loadbalancing-algorithm) can be removed by setting its value to nil adjust test for manifest push: options {key:nil} should not modify the existing value
1 parent d5e369c commit 52f1a38

File tree

6 files changed

+242
-48
lines changed

6 files changed

+242
-48
lines changed

app/actions/manifest_route_update.rb

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,9 @@ def find_or_create_valid_route(app, manifest_route, user_audit_info)
9292
domain: existing_domain,
9393
manifest_triggered: true
9494
)
95-
elsif route[:options] != manifest_route[:options]
95+
elsif manifest_route[:options] && route[:options] != manifest_route[:options]
96+
# remove nil values from options
97+
manifest_route[:options] = manifest_route[:options].compact
9698
message = RouteUpdateMessage.new({
9799
'options' => manifest_route[:options]
98100
})

app/actions/route_update.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ def update(route:, message:)
1111
route.options.merge(message.options)
1212
end
1313
end
14+
1415
route.save
1516
MetadataUpdate.update(route, message)
1617
end

lib/cloud_controller/app_manifest/manifest_route.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ def self.parse(route, options=nil)
1919

2020
if options
2121
attrs[:options] = {}
22-
attrs[:options][:lb_algo] = options[:'loadbalancing-algorithm'] if options[:'loadbalancing-algorithm']
22+
attrs[:options][:lb_algo] = options[:'loadbalancing-algorithm'] if options.key?(:'loadbalancing-algorithm')
2323
end
2424

2525
ManifestRoute.new(attrs)

spec/request/space_manifests_spec.rb

Lines changed: 136 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -606,7 +606,7 @@
606606
before do
607607
app1_model.web_processes.first.update(state: VCAP::CloudController::ProcessModel::STARTED, instances: 4)
608608
space.update(space_quota_definition:
609-
VCAP::CloudController::SpaceQuotaDefinition.make(organization: space.organization, log_rate_limit: 0))
609+
VCAP::CloudController::SpaceQuotaDefinition.make(organization: space.organization, log_rate_limit: 0))
610610
end
611611

612612
it 'successfully applies the manifest' do
@@ -625,54 +625,171 @@
625625
end
626626

627627
describe 'route options' do
628-
context 'when an empty route options hash is provided' do
628+
context 'when an invalid route option is provided' do
629629
let(:yml_manifest) do
630630
{
631631
'applications' => [
632632
{
633633
'name' => app1_model.name,
634634
'routes' => [
635635
{ 'route' => "https://#{route.host}.#{route.domain.name}",
636-
'options' => {} }
636+
'options' => {
637+
'doesnt-exist' => 'doesnt-exist'
638+
} }
637639
]
638640
}
639641
]
640642
}.to_yaml
641643
end
642644

643-
it 'applies the manifest' do
645+
it 'returns a 422' do
644646
post "/v3/spaces/#{space.guid}/actions/apply_manifest", yml_manifest, yml_headers(user_header)
645647

646-
expect(last_response.status).to eq(202)
648+
expect(last_response).to have_status_code(422)
649+
expect(last_response).to have_error_message('Routes contains invalid route options')
647650
end
648651
end
649652

650-
context 'when an invalid route option is provided' do
651-
let(:yml_manifest) do
652-
{
653+
context 'updating existing route options' do
654+
# using loadbalancing-algorithm as an example since it is the only route option currently supported
655+
before do
656+
yml_manifest = {
653657
'applications' => [
654-
{
655-
'name' => app1_model.name,
658+
{ 'name' => app1_model.name,
656659
'routes' => [
657-
{ 'route' => "https://#{route.host}.#{route.domain.name}",
660+
{ 'route' => "https://round-robin-app.#{shared_domain.name}",
658661
'options' => {
659-
'doesnt-exist' => 'doesnt-exist'
662+
'loadbalancing-algorithm' => 'round-robin'
660663
} }
661-
]
662-
}
664+
] }
663665
]
664666
}.to_yaml
667+
668+
# apply the manifest with the route option
669+
post "/v3/spaces/#{space.guid}/actions/apply_manifest", yml_manifest, yml_headers(user_header)
670+
671+
expect(last_response.status).to eq(202)
672+
job_guid = VCAP::CloudController::PollableJobModel.last.guid
673+
674+
Delayed::Worker.new.work_off
675+
expect(VCAP::CloudController::PollableJobModel.find(guid: job_guid)).to be_complete, VCAP::CloudController::PollableJobModel.find(guid: job_guid).cf_api_error
676+
app1_model.reload
677+
expect(app1_model.routes.first.options).to eq({ 'lb_algo' => 'round-robin' })
665678
end
666679

667-
it 'returns a 422' do
680+
it 'updates the route option when a new value is provided' do
681+
yml_manifest = {
682+
'applications' => [
683+
{ 'name' => app1_model.name,
684+
'routes' => [
685+
{ 'route' => "https://round-robin-app.#{shared_domain.name}",
686+
'options' => {
687+
'loadbalancing-algorithm' => 'least-connections'
688+
} }
689+
] }
690+
]
691+
}.to_yaml
692+
668693
post "/v3/spaces/#{space.guid}/actions/apply_manifest", yml_manifest, yml_headers(user_header)
669694

670-
expect(last_response).to have_status_code(422)
671-
expect(last_response).to have_error_message('Routes contains invalid route options')
695+
expect(last_response.status).to eq(202)
696+
job_guid = VCAP::CloudController::PollableJobModel.last.guid
697+
698+
Delayed::Worker.new.work_off
699+
expect(VCAP::CloudController::PollableJobModel.find(guid: job_guid)).to be_complete, VCAP::CloudController::PollableJobModel.find(guid: job_guid).cf_api_error
700+
app1_model.reload
701+
expect(app1_model.routes.first.options).to eq({ 'lb_algo' => 'least-connections' })
702+
end
703+
704+
it 'does not modify any route options when the options hash is not provided' do
705+
yml_manifest = {
706+
'applications' => [
707+
{ 'name' => app1_model.name,
708+
'routes' => [
709+
{ 'route' => "https://round-robin-app.#{shared_domain.name}" }
710+
] }
711+
]
712+
}.to_yaml
713+
714+
# apply the manifest with the route option
715+
post "/v3/spaces/#{space.guid}/actions/apply_manifest", yml_manifest, yml_headers(user_header)
716+
717+
expect(last_response.status).to eq(202)
718+
job_guid = VCAP::CloudController::PollableJobModel.last.guid
719+
720+
Delayed::Worker.new.work_off
721+
expect(VCAP::CloudController::PollableJobModel.find(guid: job_guid)).to be_complete, VCAP::CloudController::PollableJobModel.find(guid: job_guid).cf_api_error
722+
app1_model.reload
723+
expect(app1_model.routes.first.options).to eq({ 'lb_algo' => 'round-robin' })
724+
end
725+
726+
it 'does not modify any route options options: nil is provided' do
727+
yml_manifest = {
728+
'applications' => [
729+
{ 'name' => app1_model.name,
730+
'routes' => [
731+
{ 'route' => "https://round-robin-app.#{shared_domain.name}",
732+
'options' => nil }
733+
] }
734+
]
735+
}.to_yaml
736+
737+
# apply the manifest with the route option
738+
post "/v3/spaces/#{space.guid}/actions/apply_manifest", yml_manifest, yml_headers(user_header)
739+
740+
expect(last_response.status).to eq(202)
741+
job_guid = VCAP::CloudController::PollableJobModel.last.guid
742+
743+
Delayed::Worker.new.work_off
744+
expect(VCAP::CloudController::PollableJobModel.find(guid: job_guid)).to be_complete, VCAP::CloudController::PollableJobModel.find(guid: job_guid).cf_api_error
745+
app1_model.reload
746+
expect(app1_model.routes.first.options).to eq({ 'lb_algo' => 'round-robin' })
747+
end
748+
749+
it 'does not modify any route options if an empty options hash is provided' do
750+
yml_manifest = {
751+
'applications' => [
752+
{ 'name' => app1_model.name,
753+
'routes' => [
754+
{ 'route' => "https://round-robin-app.#{shared_domain.name}",
755+
'options' => {} }
756+
] }
757+
]
758+
}.to_yaml
759+
760+
# apply the manifest with the route option
761+
post "/v3/spaces/#{space.guid}/actions/apply_manifest", yml_manifest, yml_headers(user_header)
762+
763+
expect(last_response.status).to eq(202)
764+
765+
app1_model.reload
766+
expect(app1_model.routes.first.options).to eq({ 'lb_algo' => 'round-robin' })
767+
end
768+
769+
it 'does not modify any option when options: { key: nil } is provided' do
770+
yml_manifest = {
771+
'applications' => [
772+
{ 'name' => app1_model.name,
773+
'routes' => [
774+
{ 'route' => "https://round-robin-app.#{shared_domain.name}",
775+
'options' => {
776+
'loadbalancing-algorithm' => nil
777+
} }
778+
] }
779+
]
780+
}.to_yaml
781+
782+
# apply the manifest with the route option
783+
post "/v3/spaces/#{space.guid}/actions/apply_manifest", yml_manifest, yml_headers(user_header)
784+
785+
expect(last_response.status).to eq(202)
786+
787+
app1_model.reload
788+
expect(app1_model.routes.first.options).to eq({ 'lb_algo' => 'round-robin' })
672789
end
673790
end
674791

675-
context 'loadbalancing-algorithm' do
792+
context 'route-option: loadbalancing-algorithm' do
676793
context 'when the loadbalancing-algorithm is not supported' do
677794
let(:yml_manifest) do
678795
{
@@ -713,7 +830,7 @@
713830
}.to_yaml
714831
end
715832

716-
it 'adds and updates the loadbalancing-algorithm' do
833+
it 'adds the loadbalancing-algorithm' do
717834
post "/v3/spaces/#{space.guid}/actions/apply_manifest", yml_manifest, yml_headers(user_header)
718835

719836
expect(last_response.status).to eq(202)
@@ -724,31 +841,6 @@
724841

725842
app1_model.reload
726843
expect(app1_model.routes.first.options).to eq({ 'lb_algo' => 'round-robin' })
727-
728-
### update the loadbalancing-algorithm from the route
729-
730-
yml_manifest = {
731-
'applications' => [
732-
{ 'name' => app1_model.name,
733-
'routes' => [
734-
{ 'route' => "https://round-robin-app.#{shared_domain.name}",
735-
'options' => {
736-
'loadbalancing-algorithm' => 'least-connections'
737-
} }
738-
] }
739-
]
740-
}.to_yaml
741-
742-
post "/v3/spaces/#{space.guid}/actions/apply_manifest", yml_manifest, yml_headers(user_header)
743-
744-
expect(last_response.status).to eq(202)
745-
job_guid = VCAP::CloudController::PollableJobModel.last.guid
746-
747-
Delayed::Worker.new.work_off
748-
expect(VCAP::CloudController::PollableJobModel.find(guid: job_guid)).to be_complete, VCAP::CloudController::PollableJobModel.find(guid: job_guid).cf_api_error
749-
750-
app1_model.reload
751-
expect(app1_model.routes.first.options).to eq({ 'lb_algo' => 'least-connections' })
752844
end
753845
end
754846
end

0 commit comments

Comments
 (0)