ui: [BUGFIX] Re-enable namespace menus whilst editing intentions (#11095)

This PR supersedes #10706 and fixes #10686 whilst making sure that saving intentions continues to work.

The original fix in #10706 ignored the change action configured for the change event on the menus, meaning that the selected source/destination namespace could not be set by the user when editing/creating intentions. This, coupled with the fact that using the later intention exact endpoint for API requests endpoint means that you could not use wildcard namespaces for saving intentions.

All in all this meant that intentions could no longer be saved using the UI (whilst using ENT)

This PR reverts #10706 to fix the intention saving issue, and adds a fix for the original visual issue of nspaces doubling up in the menu once clicked. This meant repeating the existing functionality for nspaces aswell as services. It did seem strange to me that the original issue was only apparent for the nspace menus and not the service menus which should all function exactly the same way.

There is potentially more to come here partly related to what the exact functionality should be, but I'm working with other folks to figure out what the best way forwards is longer term. In the meantime this brings us back to the original functionality with the visual issue fixed.

Squashed commits:

* Revert "ui: Fix dropdown option duplications (#10706)"

This reverts commit eb5512fb74.

* ui: Ensure additional nspaces are added to the unique list of nspaces

* Add some acceptance tests
This commit is contained in:
John Cowen 2021-09-22 10:21:20 +01:00 committed by GitHub
parent aee8a9511d
commit cfbd1bb84e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 83 additions and 28 deletions

3
.changelog/11095.txt Normal file
View File

@ -0,0 +1,3 @@
```release-note:bug
ui: **(Enterprise Only)** Fix saving intentions with namespaced source/destination
```

View File

@ -39,7 +39,7 @@
@buildSuggestion={{action "createNewLabel" "Use a Consul Namespace called '{{term}}'"}}
@showCreateWhen={{action "isUnique" nspaces}}
@onCreate={{action onchange "SourceNS"}}
@onChange={{fn (mut this.SourceNS)}} as |nspace|>
@onChange={{action onchange "SourceNS"}} as |nspace|>
{{#if (eq nspace.Name '*') }}
* (All Namespaces)
{{else}}
@ -88,7 +88,7 @@
@buildSuggestion={{action "createNewLabel" "Use a future Consul Namespace called '{{term}}'"}}
@showCreateWhen={{action "isUnique" nspaces}}
@onCreate={{action onchange "DestinationNS"}}
@onChange={{fn (mut this.DestinationNS)}} as |nspace|>
@onChange={{action onchange "DestinationNS"}} as |nspace|>
{{#if (eq nspace.Name '*') }}
* (All Namespaces)
{{else}}

View File

@ -119,7 +119,7 @@ export default class ConsulIntentionForm extends Component {
change(e, form, item) {
const target = e.target;
let name, selected, match;
let name, selected;
switch (target.name) {
case 'SourceName':
case 'DestinationName':
@ -140,21 +140,24 @@ export default class ConsulIntentionForm extends Component {
// basically the difference between
// `item.DestinationName` and just `DestinationName`
// see if the name is already in the list
match = this.services.filterBy('Name', name);
if (match.length === 0) {
// if its not make a new 'fake' Service that doesn't exist yet
// and add it to the possible services to make an intention between
selected = { Name: name };
switch (target.name) {
case 'SourceName':
case 'DestinationName':
if (this.services.filterBy('Name', name).length === 0) {
selected = { Name: name };
this.services = [selected].concat(this.services.toArray());
}
break;
case 'SourceNS':
case 'DestinationNS':
if (this.nspaces.filterBy('Name', name).length === 0) {
selected = { Name: name };
this.nspaces = [selected].concat(this.nspaces.toArray());
break;
}
break;
}
this[target.name] = selected;
break;

View File

@ -15,6 +15,10 @@ Feature: dc / intentions / create: Intention Create
- Name: cache
Kind: ~
---
And 1 nspace model from yaml
---
- Name: nspace-0
---
When I visit the intention page for yaml
---
dc: datacenter
@ -31,17 +35,26 @@ Feature: dc / intentions / create: Intention Create
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:nth-child(2)"
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:nth-child(2)"
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
# TODO: When namespace is empty we expect *
# Then a PUT request was made to "/v1/connect/intentions/exact?source=@namespace%2Fweb&destination=@namespace%2Fdb&dc=datacenter" from yaml
# ---
# body:
# SourceName: web
# DestinationName: db
# Action: deny
# ---
Then a PUT request was made to "/v1/connect/intentions/exact?source=nspace-0%2Fweb&destination=nspace-0%2Fdb&dc=datacenter" from yaml
---
body:
SourceName: web
DestinationName: db
SourceNS: nspace-0
DestinationNS: nspace-0
Action: deny
---
Then the url should be /datacenter/intentions
And the title should be "Intentions - Consul"
And "[data-notification]" has the "notification-update" class

View File

@ -31,6 +31,42 @@ Feature: dc / intentions / filtered-select: Intention Service Select Dropdowns
| source |
| destination |
---------------
@onlyNamespaceable
Scenario: Opening and closing the nspace [Name] dropdown doesn't double up items
Given 1 datacenter model with the value "datacenter"
And 2 nspace models from yaml
---
- Name: nspace-0
- Name: nspace-1
---
When I visit the intention page for yaml
---
dc: datacenter
---
Then the url should be /datacenter/intentions/create
Given a network latency of 60000
And I click "[data-test-[Name]-nspace] .ember-power-select-trigger"
Then I see the text "* (All Namespaces)" in ".ember-power-select-option:nth-last-child(3)"
Then I see the text "nspace-0" in ".ember-power-select-option:nth-last-child(2)"
Then I see the text "nspace-1" in ".ember-power-select-option:last-child"
And I click ".ember-power-select-option:last-child"
And I click "[data-test-[Name]-nspace] .ember-power-select-trigger"
And I click ".ember-power-select-option:last-child"
And I click "[data-test-[Name]-nspace] .ember-power-select-trigger"
And I click ".ember-power-select-option:last-child"
And I click "[data-test-[Name]-nspace] .ember-power-select-trigger"
Then I don't see the text "nspace-1" in ".ember-power-select-option:nth-last-child(6)"
Then I don't see the text "nspace-1" in ".ember-power-select-option:nth-last-child(5)"
Then I don't see the text "nspace-1" in ".ember-power-select-option:nth-last-child(4)"
Then I see the text "* (All Namespaces)" in ".ember-power-select-option:nth-last-child(3)"
Then I see the text "nspace-0" in ".ember-power-select-option:nth-last-child(2)"
Then I see the text "nspace-1" in ".ember-power-select-option:last-child"
Where:
---------------
| Name |
| source |
| destination |
---------------
Scenario: Opening the [Name] dropdown with 2 services with the same name from different nspaces
Given 1 datacenter model with the value "datacenter"
And 2 service models from yaml

View File

@ -14,11 +14,11 @@ export default function(scenario, assert, pauseUntil, find, currentURL, clipboar
return retry();
}, `Expected to see "${text}" in "${selector}"`);
})
.then(['I see the text "$text" in "$selector"'], function(text, selector) {
const textContent = find(selector).textContent;
assert.ok(
.then([`I${dont} see the text "$text" in "$selector"`], function(negative, text, selector) {
const textContent = (find(selector) || { textContent: '' }).textContent;
assert[negative ? 'notOk' : 'ok'](
textContent.indexOf(text) !== -1,
`Expected to see "${text}" in "${selector}", was "${textContent}"`
`Expected${negative ? ' not' : ''} to see "${text}" in "${selector}", was "${textContent}"`
);
})
.then(['I copied "$text"'], function(text) {