ui: [BUGFIX] Fixes an issue when editing intentions from the service > intentions sub tab (#11937)

We recently changed the intentions form to take a full model of a dc rather than just the string identifier (so {Name: 'dc', Primary: true} vs just 'dc' in order to know whether the DC is the primary or not.

Unfortunately, we only did this on the global intentions page not the per service intentions page. This makes it impossible to save an intention from the per service intention page (whilst you can still save intentions from the global intention page as normal).

The fix here pretty much copy/pastes the approach taken in the global intention edit template over to the per service intention edit template.

Tests have been added for creation in the per service intention section, which again are pretty much just copied from the global one, unfortunately this didn't exist previously which would have helped prevent this.
This commit is contained in:
John Cowen 2022-01-07 19:09:40 +00:00 committed by GitHub
parent 86e885fc5b
commit 3ab747109b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 170 additions and 15 deletions

3
.changelog/11937.txt Normal file
View File

@ -0,0 +1,3 @@
```release-note:bug
ui: Fixes an issue saving intentions when editing per service intentions
```

View File

@ -1,17 +1,44 @@
<Route <Route
@name={{routeName}} @name={{routeName}}
as |route|> as |route|>
{{#let (not (can "write intention for service" item=item.Service)) as |readOnly|}} {{#let
(not (can "write intention for service" item=item.Service))
as |readOnly|}}
<DataLoader @src={{
uri '/${partition}/${nspace}/${dc}/intention/${id}'
(hash
partition=route.params.partition
nspace=route.params.nspace
dc=route.params.dc
id=(or route.params.intention_id '')
)
}}
as |loader|>
<BlockSlot @name="error">
<ErrorState
@error={{loader.error}}
@login={{route.model.app.login.open}}
/>
</BlockSlot>
<BlockSlot @name="loaded">
{{#let
loader.data
as |item|}}
<Consul::Intention::Form <Consul::Intention::Form
@nspace={{'*'}}
@dc={{route.params.dc}}
@partition={{route.params.partition}}
@src={{route.params.intention_id}}
@readonly={{readOnly}} @readonly={{readOnly}}
@item={{item}}
@dc={{route.model.dc}}
@nspace={{route.params.nspace}}
@partition={{route.params.partition}}
@autofill={{hash @autofill={{hash
DestinationName=route.params.name DestinationName=route.params.name
}} }}
@onsubmit={{transition-to 'dc.services.show.intentions.index'}} @onsubmit={{transition-to 'dc.services.show.intentions.index'}}
/> />
{{/let}}
</BlockSlot>
</DataLoader>
{{/let}} {{/let}}
</Route> </Route>

View File

@ -0,0 +1,108 @@
@setupApplicationTest
Feature: dc / services / intentions / create: Intention Create per Service
@onlyNamespaceable
Scenario: with namespaces enabled
Given 1 datacenter model with the value "datacenter"
And 3 service models from yaml
---
- Name: web
Kind: ~
- Name: db
Kind: ~
- Name: cache
Kind: ~
---
And 1 instance model from yaml
---
- Service:
ID: db
Service: db
Kind: ~
---
And 1 nspace model from yaml
---
- Name: nspace-0
---
When I visit the intention page for yaml
---
dc: datacenter
service: db
---
Then the url should be /datacenter/services/db/intentions/create
# Set source
And I click "[data-test-source-element] .ember-power-select-trigger"
And I type "web" into ".ember-power-select-search-input"
And I click ".ember-power-select-option:first-child"
Then I see the text "web" in "[data-test-source-element] .ember-power-select-selected-item"
# Set destination
And I click "[data-test-destination-element] .ember-power-select-trigger"
And I type "db" into ".ember-power-select-search-input"
And I click ".ember-power-select-option:first-child"
Then I see the text "db" in "[data-test-destination-element] .ember-power-select-selected-item"
# Set source nspace
And I click "[data-test-source-nspace] .ember-power-select-trigger"
And I click ".ember-power-select-option:last-child"
Then I see the text "nspace-0" in "[data-test-source-nspace] .ember-power-select-selected-item"
# Set destination nspace
And I click "[data-test-destination-nspace] .ember-power-select-trigger"
And I click ".ember-power-select-option:last-child"
Then I see the text "nspace-0" in "[data-test-destination-nspace] .ember-power-select-selected-item"
# Specifically set deny
And I click ".value-deny"
And I submit
Then a PUT request was made to "/v1/connect/intentions/exact?source=default%2Fnspace-0%2Fweb&destination=default%2Fnspace-0%2Fdb&dc=datacenter" from yaml
---
body:
SourceName: web
DestinationName: db
SourceNS: nspace-0
DestinationNS: nspace-0
SourcePartition: default
DestinationPartition: default
Action: deny
---
Then the url should be /datacenter/services/db/intentions
And "[data-notification]" has the "notification-update" class
And "[data-notification]" has the "success" class
@notNamespaceable
Scenario: with namespaces disabled
Given 1 datacenter model with the value "datacenter"
And 3 instance models from yaml
---
- Service:
ID: web
Service: web
Kind: ~
- Service:
ID: db
Service: db
Kind: ~
- Service:
ID: cache
Service: cache
Kind: ~
---
When I visit the intention page for yaml
---
dc: datacenter
service: db
---
Then the url should be /datacenter/services/db/intentions/create
# Set source
And I click "[data-test-source-element] .ember-power-select-trigger"
And I type "web" into ".ember-power-select-search-input"
And I click ".ember-power-select-option:first-child"
Then I see the text "web" in "[data-test-source-element] .ember-power-select-selected-item"
# Specifically set deny
And I click ".value-deny"
And I submit
Then a PUT request was made to "/v1/connect/intentions/exact?source=default%2Fdefault%2Fweb&destination=default%2Fdefault%2Fdb&dc=datacenter" from yaml
---
body:
SourceName: web
DestinationName: db
Action: deny
---
Then the url should be /datacenter/services/db/intentions
And "[data-notification]" has the "notification-update" class
And "[data-notification]" has the "success" class

View File

@ -1,5 +1,5 @@
@setupApplicationTest @setupApplicationTest
Feature: dc / services / show / intentions: Intentions per service Feature: dc / services / show / intentions / index: Intentions per service
Background: Background:
Given 1 datacenter model with the value "dc1" Given 1 datacenter model with the value "dc1"
And 1 node models And 1 node models

View File

@ -1,4 +1,4 @@
import steps from '../../../steps'; import steps from '../../../../steps';
// step definitions that are shared between features should be moved to the // step definitions that are shared between features should be moved to the
// tests/acceptance/steps/steps.js file // tests/acceptance/steps/steps.js file

View File

@ -0,0 +1,10 @@
import steps from '../../../../steps';
// step definitions that are shared between features should be moved to the
// tests/acceptance/steps/steps.js file
export default function(assert) {
return steps(assert).then('I should find a file', function() {
assert.ok(true, this.step);
});
}

View File

@ -5,9 +5,11 @@ export default function(type) {
requests = ['/v1/catalog/datacenters']; requests = ['/v1/catalog/datacenters'];
break; break;
case 'service': case 'service':
case 'instance':
requests = ['/v1/internal/ui/services', '/v1/health/service/']; requests = ['/v1/internal/ui/services', '/v1/health/service/'];
break; break;
case 'instance':
requests = ['/v1/health/service/'];
break;
case 'proxy': case 'proxy':
requests = ['/v1/catalog/connect']; requests = ['/v1/catalog/connect'];
break; break;

View File

@ -10,7 +10,12 @@ export default function(
) { ) {
return { return {
scope: 'main', scope: 'main',
visit: visitable(['/:dc/intentions/:intention', '/:dc/intentions/create']), visit: visitable([
'/:dc/intentions/:intention',
'/:dc/services/:service/intentions/:intention',
'/:dc/services/:service/intentions/create',
'/:dc/intentions/create',
]),
permissions: { permissions: {
create: { create: {
scope: '[data-test-create-permission]', scope: '[data-test-create-permission]',