ui: Add initial partition support to intentions (#11129)
* ui: Add initial partition support to intentions
This commit is contained in:
parent
78a3b9f3e1
commit
b19e14e8a8
|
@ -0,0 +1,4 @@
|
|||
```release-note:improvement
|
||||
ui: Add initial support for partitions to intentions
|
||||
```
|
||||
|
|
@ -7,10 +7,11 @@ import { get } from '@ember/object';
|
|||
// will give us all the intentions that have the `ns` as either the SourceNS or
|
||||
// the DestinationNS.
|
||||
// We currently list intentions by the * wildcard namespace for back compat reasons
|
||||
// FIXME: Is now a good time to change this behaviour ^ ?
|
||||
|
||||
// TODO: Update to use this.formatDatacenter()
|
||||
export default class IntentionAdapter extends Adapter {
|
||||
requestForQuery(request, { dc, ns, filter, index, uri }) {
|
||||
requestForQuery(request, { dc, ns, partition, filter, index, uri }) {
|
||||
return request`
|
||||
GET /v1/connect/intentions?${{ dc }}
|
||||
X-Request-ID: ${uri}${
|
||||
|
@ -21,7 +22,7 @@ export default class IntentionAdapter extends Adapter {
|
|||
}
|
||||
|
||||
${{
|
||||
partition: '',
|
||||
partition: '*',
|
||||
ns: '*',
|
||||
index,
|
||||
filter,
|
||||
|
@ -36,14 +37,21 @@ export default class IntentionAdapter extends Adapter {
|
|||
|
||||
// get the information we need from the id, which has been previously
|
||||
// encoded
|
||||
const [SourceNS, SourceName, DestinationNS, DestinationName] = id
|
||||
.split(':')
|
||||
.map(decodeURIComponent);
|
||||
const [
|
||||
SourcePartition,
|
||||
SourceNS,
|
||||
SourceName,
|
||||
DestinationPartition,
|
||||
DestinationNS,
|
||||
DestinationName,
|
||||
] = id.split(':').map(decodeURIComponent);
|
||||
|
||||
// FIXME: Service and Namespace are encoded into the URL here
|
||||
// guessing we need to do the same thing for Partitions
|
||||
return request`
|
||||
GET /v1/connect/intentions/exact?${{
|
||||
source: `${SourceNS}/${SourceName}`,
|
||||
destination: `${DestinationNS}/${DestinationName}`,
|
||||
source: `${SourcePartition}/${SourceNS}/${SourceName}`,
|
||||
destination: `${DestinationPartition}/${DestinationNS}/${DestinationName}`,
|
||||
dc: dc,
|
||||
}}
|
||||
Cache-Control: no-store
|
||||
|
@ -54,10 +62,12 @@ export default class IntentionAdapter extends Adapter {
|
|||
|
||||
requestForCreateRecord(request, serialized, data) {
|
||||
const body = {
|
||||
SourceNS: serialized.SourceNS,
|
||||
DestinationNS: serialized.DestinationNS,
|
||||
SourceName: serialized.SourceName,
|
||||
DestinationName: serialized.DestinationName,
|
||||
SourceNS: serialized.SourceNS,
|
||||
DestinationNS: serialized.DestinationNS,
|
||||
SourcePartition: serialized.SourcePartition,
|
||||
DestinationPartition: serialized.DestinationPartition,
|
||||
SourceType: serialized.SourceType,
|
||||
Meta: serialized.Meta,
|
||||
Description: serialized.Description,
|
||||
|
@ -72,10 +82,12 @@ export default class IntentionAdapter extends Adapter {
|
|||
body.Permissions = serialized.Permissions;
|
||||
}
|
||||
}
|
||||
// FIXME: Service and Namespace are encoded into the URL here
|
||||
// guessing we need to do the same thing for Partitions
|
||||
return request`
|
||||
PUT /v1/connect/intentions/exact?${{
|
||||
source: `${data.SourceNS}/${data.SourceName}`,
|
||||
destination: `${data.DestinationNS}/${data.DestinationName}`,
|
||||
source: `${data.SourcePartition}/${data.SourceNS}/${data.SourceName}`,
|
||||
destination: `${data.DestinationPartition}/${data.DestinationNS}/${data.DestinationName}`,
|
||||
dc: data.Datacenter,
|
||||
}}
|
||||
|
||||
|
@ -85,16 +97,20 @@ export default class IntentionAdapter extends Adapter {
|
|||
|
||||
requestForUpdateRecord(request, serialized, data) {
|
||||
// you can no longer save Destinations
|
||||
delete serialized.DestinationNS;
|
||||
delete serialized.DestinationName;
|
||||
delete serialized.DestinationNS;
|
||||
// FIXME: Does the above comment stand for partitions also?
|
||||
delete serialized.DestinationPartition;
|
||||
return this.requestForCreateRecord(...arguments);
|
||||
}
|
||||
|
||||
requestForDeleteRecord(request, serialized, data) {
|
||||
// FIXME: Service and Namespace are encoded into the URL here
|
||||
// guessing we need to do the same thing for Partitions
|
||||
return request`
|
||||
DELETE /v1/connect/intentions/exact?${{
|
||||
source: `${data.SourceNS}/${data.SourceName}`,
|
||||
destination: `${data.DestinationNS}/${data.DestinationName}`,
|
||||
source: `${data.SourcePartition}/${data.SourceNS}/${data.SourceName}`,
|
||||
destination: `${data.DestinationPartition}/${data.DestinationNS}/${data.DestinationName}`,
|
||||
dc: data.Datacenter,
|
||||
}}
|
||||
`;
|
||||
|
|
|
@ -28,7 +28,7 @@
|
|||
<em>Search for an existing service, or enter any Service name.</em>
|
||||
{{/if}}
|
||||
</label>
|
||||
{{#if (env 'CONSUL_NSPACES_ENABLED')}}
|
||||
{{#if (can 'choose nspaces')}}
|
||||
<label data-test-source-nspace class="type-select{{if item.error.SourceNS ' has-error'}}">
|
||||
<span>Source Namespace</span>
|
||||
<PowerSelectWithCreate
|
||||
|
@ -50,7 +50,30 @@
|
|||
<em>Search for an existing namespace, or enter any Namespace name.</em>
|
||||
{{/if}}
|
||||
</label>
|
||||
{{/if}}
|
||||
{{/if}}
|
||||
{{#if (can 'choose partitions')}}
|
||||
<label data-test-source-partition class="type-select{{if item.error.SourcePartition ' has-error'}}">
|
||||
<span>Source Partition</span>
|
||||
<PowerSelectWithCreate
|
||||
@disabled={{not create}}
|
||||
@options={{partitions}}
|
||||
@selected={{SourcePartition}}
|
||||
@searchPlaceholder="Type partition name"
|
||||
@buildSuggestion={{action "createNewLabel" "Use a Consul Partition called '{{term}}'"}}
|
||||
@showCreateWhen={{action "isUnique" partitions}}
|
||||
@onCreate={{action onchange "SourcePartition"}}
|
||||
@onChange={{action onchange "SourcePartition"}} as |partition|>
|
||||
{{#if (eq partition.Name '*') }}
|
||||
* (All Partitions)
|
||||
{{else}}
|
||||
{{partition.Name}}
|
||||
{{/if}}
|
||||
</PowerSelectWithCreate>
|
||||
{{#if create}}
|
||||
<em>Search for an existing partition, or enter any Partition name.</em>
|
||||
{{/if}}
|
||||
</label>
|
||||
{{/if}}
|
||||
</fieldset>
|
||||
<fieldset>
|
||||
<h2>Destination</h2>
|
||||
|
@ -76,7 +99,7 @@
|
|||
<em>Search for an existing service, or enter any Service name.</em>
|
||||
{{/if}}
|
||||
</label>
|
||||
{{#if (env 'CONSUL_NSPACES_ENABLED')}}
|
||||
{{#if (can 'choose nspaces')}}
|
||||
<label data-test-destination-nspace class="type-select{{if item.error.DestinationNS ' has-error'}}">
|
||||
<span>Destination Namespace</span>
|
||||
<PowerSelectWithCreate
|
||||
|
@ -99,7 +122,31 @@
|
|||
<em>For the destination, you may choose any namespace for which you have access.</em>
|
||||
{{/if}}
|
||||
</label>
|
||||
{{/if}}
|
||||
{{/if}}
|
||||
{{#if (can 'choose partitions')}}
|
||||
<label data-test-destination-partition class="type-select{{if item.error.DestinationPartition ' has-error'}}">
|
||||
<span>Destination Partition</span>
|
||||
<PowerSelectWithCreate
|
||||
@disabled={{not create}}
|
||||
@options={{partitions}}
|
||||
@searchField="Name"
|
||||
@selected={{DestinationPartition}}
|
||||
@searchPlaceholder="Type partition name"
|
||||
@buildSuggestion={{action "createNewLabel" "Use a future Consul Partition called '{{term}}'"}}
|
||||
@showCreateWhen={{action "isUnique" partitions}}
|
||||
@onCreate={{action onchange "DestinationPartition"}}
|
||||
@onChange={{action onchange "DestinationPartition"}} as |partition|>
|
||||
{{#if (eq partition.Name '*') }}
|
||||
* (All Partitions)
|
||||
{{else}}
|
||||
{{partition.Name}}
|
||||
{{/if}}
|
||||
</PowerSelectWithCreate>
|
||||
{{#if create}}
|
||||
<em>For the destination, you may choose any partition for which you have access.</em>
|
||||
{{/if}}
|
||||
</label>
|
||||
{{/if}}
|
||||
</fieldset>
|
||||
</div>
|
||||
<fieldset>
|
||||
|
|
|
@ -95,6 +95,17 @@ as |api|>
|
|||
/>
|
||||
{{/if}}
|
||||
|
||||
{{#if (can 'use partitions')}}
|
||||
<DataSource
|
||||
@src={{uri '/*/*/${dc}/partitions'
|
||||
(hash
|
||||
dc=@dc
|
||||
)
|
||||
}}
|
||||
@onchange={{action this.createPartitions item}}
|
||||
/>
|
||||
{{/if}}
|
||||
|
||||
{{#if (and api.isCreate this.isManagedByCRDs)}}
|
||||
<Consul::Intention::Notice::CustomResource @type="warning" />
|
||||
{{/if}}
|
||||
|
@ -103,11 +114,14 @@ as |api|>
|
|||
>
|
||||
<Consul::Intention::Form::Fieldsets
|
||||
@nspaces={{this.nspaces}}
|
||||
@partitions={{this.partitions}}
|
||||
@services={{this.services}}
|
||||
@SourceName={{this.SourceName}}
|
||||
@SourceNS={{this.SourceNS}}
|
||||
@SourcePartition={{this.SourcePartition}}
|
||||
@DestinationName={{this.DestinationName}}
|
||||
@DestinationNS={{this.DestinationNS}}
|
||||
@DestinationPartition={{this.DestinationPartition}}
|
||||
@item={{item}}
|
||||
@disabled={{api.disabled}}
|
||||
@create={{api.isCreate}}
|
||||
|
|
|
@ -12,6 +12,10 @@ export default class ConsulIntentionForm extends Component {
|
|||
@tracked SourceNS;
|
||||
@tracked DestinationNS;
|
||||
|
||||
@tracked partitions;
|
||||
@tracked SourcePartition;
|
||||
@tracked DestinationPartition;
|
||||
|
||||
@tracked isManagedByCRDs;
|
||||
|
||||
modal = null; // reference to the warning modal
|
||||
|
@ -115,6 +119,28 @@ export default class ConsulIntentionForm extends Component {
|
|||
this.DestinationNS = destination;
|
||||
}
|
||||
|
||||
@action
|
||||
createPartitions(item, e) {
|
||||
// Partitions in the menus should:
|
||||
// 1. Include an 'All Partitions' option
|
||||
// 2. Include the current SourcePartition and DestinationPartition incase they don't exist yet
|
||||
let items = e.data.toArray().sort((a, b) => a.Name.localeCompare(b.Name));
|
||||
items = [{ Name: '*' }].concat(items);
|
||||
let source = items.findBy('Name', item.SourcePartition);
|
||||
if (!source) {
|
||||
source = { Name: item.SourcePartition };
|
||||
items = [source].concat(items);
|
||||
}
|
||||
let destination = items.findBy('Name', item.DestinationPartition);
|
||||
if (!destination) {
|
||||
destination = { Name: item.DestinationPartition };
|
||||
items = [destination].concat(items);
|
||||
}
|
||||
this.partitions = items;
|
||||
this.SourcePartition = source;
|
||||
this.DestinationPartition = destination;
|
||||
}
|
||||
|
||||
@action
|
||||
change(e, form, item) {
|
||||
const target = e.target;
|
||||
|
@ -125,6 +151,8 @@ export default class ConsulIntentionForm extends Component {
|
|||
case 'DestinationName':
|
||||
case 'SourceNS':
|
||||
case 'DestinationNS':
|
||||
case 'SourcePartition':
|
||||
case 'DestinationPartition':
|
||||
name = selected = target.value;
|
||||
// Names can be selected Service EmberObjects or typed in strings
|
||||
// if its not a string, use the `Name` from the Service EmberObject
|
||||
|
@ -158,6 +186,13 @@ export default class ConsulIntentionForm extends Component {
|
|||
this.nspaces = [selected].concat(this.nspaces.toArray());
|
||||
}
|
||||
break;
|
||||
case 'SourcePartition':
|
||||
case 'DestinationPartition':
|
||||
if (this.partitions.filterBy('Name', name).length === 0) {
|
||||
selected = { Name: name };
|
||||
this.partitions = [selected].concat(this.partitions.toArray());
|
||||
}
|
||||
break;
|
||||
}
|
||||
this[target.name] = selected;
|
||||
break;
|
||||
|
|
|
@ -1,5 +1,26 @@
|
|||
.consul-intention-list {
|
||||
td.permissions {
|
||||
%consul-intention-list td.permissions {
|
||||
color: $blue-500;
|
||||
}
|
||||
}
|
||||
%consul-intention-list em {
|
||||
--word-spacing: 0.25rem;
|
||||
}
|
||||
%consul-intention-list em span::before,
|
||||
%consul-intention-list em span:first-child {
|
||||
margin-right: var(--word-spacing);
|
||||
}
|
||||
%consul-intention-list em span:last-child {
|
||||
margin-left: var(--word-spacing);
|
||||
}
|
||||
%consul-intention-list em span::before {
|
||||
@extend %as-pseudo;
|
||||
}
|
||||
%consul-intention-list span[class|='nspace']::before {
|
||||
@extend %with-folder-outline-mask;
|
||||
}
|
||||
%consul-intention-list span[class|='partition']::before {
|
||||
@extend %with-user-team-mask;
|
||||
}
|
||||
|
||||
.consul-intention-list {
|
||||
@extend %consul-intention-list;
|
||||
}
|
||||
|
|
|
@ -25,7 +25,13 @@ as |item index|>
|
|||
{{item.SourceName}}
|
||||
{{/if}}
|
||||
{{! TODO: slugify }}
|
||||
<em class={{concat 'nspace-' (or item.SourceNS 'default')}}>{{or item.SourceNS 'default'}}</em>
|
||||
<em>
|
||||
<span
|
||||
class={{concat 'partition-' (or item.SourcePartition 'default')}}
|
||||
>{{or item.SourcePartition 'default'}}</span> / <span
|
||||
class={{concat 'nspace-' (or item.SourceNS 'default')}}
|
||||
>{{or item.SourceNS 'default'}}</span>
|
||||
</em>
|
||||
</a>
|
||||
</td>
|
||||
<td class="intent intent-{{slugify item.Action}}" data-test-intention-action={{item.Action}}>
|
||||
|
@ -39,7 +45,13 @@ as |item index|>
|
|||
{{item.DestinationName}}
|
||||
{{/if}}
|
||||
{{! TODO: slugify }}
|
||||
<em class={{concat 'nspace-' (or item.DestinationNS 'default')}}>{{or item.DestinationNS 'default'}}</em>
|
||||
<em>
|
||||
<span
|
||||
class={{concat 'partition-' (or item.DestinationPartition 'default')}}
|
||||
>{{or item.DestinationPartition 'default'}}</span> / <span
|
||||
class={{concat 'nspace-' (or item.DestinationNS 'default')}}
|
||||
>{{or item.DestinationNS 'default'}}</span>
|
||||
</em>
|
||||
</span>
|
||||
</td>
|
||||
<td class="permissions">
|
||||
|
|
|
@ -4,11 +4,11 @@
|
|||
<dl>
|
||||
<dt>Destination</dt>
|
||||
<dd>
|
||||
{{item.DestinationName}}{{#if (env "CONSUL_NSPACES_ENABLED")}} / {{item.DestinationNS}}{{/if}}
|
||||
{{item.DestinationName}}{{#if (can "use partitions")}} / {{item.DestinationPartition}}{{/if}}{{#if (can "use nspaces")}} / {{item.DestinationNS}}{{/if}}
|
||||
</dd>
|
||||
<dt>Source</dt>
|
||||
<dd>
|
||||
{{item.SourceName}}{{#if (env "CONSUL_NSPACES_ENABLED")}} / {{item.SourceNS}}{{/if}}
|
||||
{{item.SourceName}}{{#if (can "use partitions")}} / {{item.SourcePartition}}{{/if}}{{#if (can "use nspaces")}} / {{item.SourceNS}}{{/if}}
|
||||
</dd>
|
||||
{{#if item.Action}}
|
||||
<dt>Action</dt>
|
||||
|
|
|
@ -12,11 +12,14 @@ export default class Intention extends Model {
|
|||
|
||||
@attr('string') Datacenter;
|
||||
@attr('string') Description;
|
||||
// FIXME: Will we have Source/DestinationPartition?
|
||||
@attr('string', { defaultValue: () => 'default' }) SourceNS;
|
||||
|
||||
@attr('string', { defaultValue: () => '*' }) SourceName;
|
||||
@attr('string', { defaultValue: () => 'default' }) DestinationNS;
|
||||
@attr('string', { defaultValue: () => '*' }) DestinationName;
|
||||
@attr('string', { defaultValue: () => 'default' }) SourceNS;
|
||||
@attr('string', { defaultValue: () => 'default' }) DestinationNS;
|
||||
@attr('string', { defaultValue: () => 'default' }) SourcePartition;
|
||||
@attr('string', { defaultValue: () => 'default' }) DestinationPartition;
|
||||
|
||||
@attr('number') Precedence;
|
||||
@attr('string', { defaultValue: () => 'consul' }) SourceType;
|
||||
@nullValue(undefined) @attr('string') Action;
|
||||
|
|
|
@ -22,7 +22,7 @@ export default class IntentionSerializer extends Serializer {
|
|||
item.LegacyID = item.ID;
|
||||
}
|
||||
item.ID = this
|
||||
.uri`${item.SourceNS}:${item.SourceName}:${item.DestinationNS}:${item.DestinationName}`;
|
||||
.uri`${item.SourcePartition}:${item.SourceNS}:${item.SourceName}:${item.DestinationPartition}:${item.DestinationNS}:${item.DestinationName}`;
|
||||
return item;
|
||||
}
|
||||
|
||||
|
@ -56,7 +56,7 @@ export default class IntentionSerializer extends Serializer {
|
|||
return respond((headers, body) => {
|
||||
body = data;
|
||||
body.ID = this
|
||||
.uri`${serialized.SourceNS}:${serialized.SourceName}:${serialized.DestinationNS}:${serialized.DestinationName}`;
|
||||
.uri`${serialized.SourcePartition}:${serialized.SourceNS}:${serialized.SourceName}:${serialized.DestinationPartition}:${serialized.DestinationNS}:${serialized.DestinationName}`;
|
||||
return this.fingerprint(primaryKey, slugKey, body.Datacenter)(body);
|
||||
});
|
||||
}
|
||||
|
|
|
@ -69,9 +69,12 @@ export default class IntentionRepository extends RepositoryService {
|
|||
let item;
|
||||
if (params.id === '') {
|
||||
const defaultNspace = this.env.var('CONSUL_NSPACES_ENABLED') ? '*' : 'default';
|
||||
const defaultPartition = this.env.var('CONSUL_PARTITIONS_ENABLED') ? '*' : 'default';
|
||||
item = await this.create({
|
||||
SourceNS: params.nspace || defaultNspace,
|
||||
DestinationNS: params.nspace || defaultNspace,
|
||||
SourcePartition: params.partition || defaultPartition,
|
||||
DestinationPartition: params.partition || defaultPartition,
|
||||
Datacenter: params.dc,
|
||||
Partition: params.partition,
|
||||
});
|
||||
|
|
|
@ -84,6 +84,9 @@ main,
|
|||
html:not(.has-nspaces) [class*='nspace-'] {
|
||||
display: none;
|
||||
}
|
||||
html:not(.has-partitions) [class*='partition-'] {
|
||||
display: none;
|
||||
}
|
||||
#wrapper {
|
||||
@extend %viewport-container;
|
||||
display: flex;
|
||||
|
|
|
@ -22,10 +22,12 @@ ${legacy ? `
|
|||
"Action": "${fake.helpers.randomize(['allow', 'deny'])}",
|
||||
`:``}
|
||||
"Description": "${fake.lorem.sentence()}",
|
||||
"SourceNS": "default",
|
||||
"SourceName": "${fake.hacker.noun()}-${i}",
|
||||
"DestinationNS": "default",
|
||||
"DestinationName": "${fake.hacker.noun()}",
|
||||
"SourceNS": "default",
|
||||
"DestinationNS": "default",
|
||||
"SourcePartition": "default",
|
||||
"DestinationPartition": "default",
|
||||
"SourceType": "${fake.helpers.randomize(['consul', 'externaluri'])}",
|
||||
${!legacy ? `
|
||||
"Permissions": [
|
||||
|
|
|
@ -6,10 +6,12 @@ return `
|
|||
"ID": "${legacy ? ID : ''}"
|
||||
${ http.method !== "PUT" ? `
|
||||
,"Description": "${fake.lorem.sentence()}",
|
||||
"SourceNS": "default",
|
||||
"SourceName": "${fake.hacker.noun()}",
|
||||
"DestinationNS": "default",
|
||||
"DestinationName": "${fake.hacker.noun()}",
|
||||
"SourceNS": "default",
|
||||
"DestinationNS": "default",
|
||||
"SourcePartition": "default",
|
||||
"DestinationPartition": "default",
|
||||
"SourceType": "${fake.helpers.randomize(['consul', 'externaluri'])}",
|
||||
${legacy ? `
|
||||
"Action": "${fake.helpers.randomize(['allow', 'deny'])}",
|
||||
|
|
|
@ -8,10 +8,12 @@ return `
|
|||
"ID": "${legacy ? ID : ''}"
|
||||
${ http.method !== "PUT" ? `
|
||||
,"Description": "${fake.lorem.sentence()}",
|
||||
"SourceNS": "${source[0]}",
|
||||
"SourceName": "${source[1]}",
|
||||
"DestinationNS": "${destination[0]}",
|
||||
"DestinationName": "${destination[1]}",
|
||||
"SourceName": "${source[2]}",
|
||||
"DestinationName": "${destination[2]}",
|
||||
"SourceNS": "${source[1]}",
|
||||
"DestinationNS": "${destination[1]}",
|
||||
"SourcePartition": "${source[0]}",
|
||||
"DestinationPartition": "${destination[0]}",
|
||||
"SourceType": "${fake.helpers.randomize(['consul', 'externaluri'])}",
|
||||
${legacy ? `
|
||||
"Action": "${fake.helpers.randomize(['allow', 'deny'])}",
|
||||
|
|
|
@ -46,13 +46,15 @@ Feature: dc / intentions / create: Intention Create
|
|||
# Specifically set deny
|
||||
And I click ".value-deny"
|
||||
And I submit
|
||||
Then a PUT request was made to "/v1/connect/intentions/exact?source=nspace-0%2Fweb&destination=nspace-0%2Fdb&dc=datacenter" from yaml
|
||||
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/intentions
|
||||
|
@ -90,7 +92,7 @@ Feature: dc / intentions / create: Intention Create
|
|||
# Specifically set deny
|
||||
And I click ".value-deny"
|
||||
And I submit
|
||||
Then a PUT request was made to "/v1/connect/intentions/exact?source=default%2Fweb&destination=default%2Fdb&dc=datacenter" from yaml
|
||||
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
|
||||
|
|
|
@ -4,10 +4,12 @@ Feature: dc / intentions / deleting: Deleting items with confirmations, success
|
|||
Given 1 datacenter model with the value "datacenter"
|
||||
And 1 intention model from yaml
|
||||
---
|
||||
SourceNS: default
|
||||
SourceName: name
|
||||
DestinationNS: default
|
||||
DestinationName: destination
|
||||
SourceNS: default
|
||||
DestinationNS: default
|
||||
SourcePartition: default
|
||||
DestinationPartition: default
|
||||
ID: ee52203d-989f-4f7a-ab5a-2bef004164ca
|
||||
Meta: ~
|
||||
---
|
||||
|
@ -19,7 +21,7 @@ Feature: dc / intentions / deleting: Deleting items with confirmations, success
|
|||
And I click actions on the intentionList.intentions
|
||||
And I click delete on the intentionList.intentions
|
||||
And I click confirmDelete on the intentionList.intentions
|
||||
Then a DELETE request was made to "/v1/connect/intentions/exact?source=default%2Fname&destination=default%2Fdestination&dc=datacenter"
|
||||
Then a DELETE request was made to "/v1/connect/intentions/exact?source=default%2Fdefault%2Fname&destination=default%2Fdefault%2Fdestination&dc=datacenter"
|
||||
And "[data-notification]" has the "notification-delete" class
|
||||
And "[data-notification]" has the "success" class
|
||||
Scenario: Deleting an intention from the intention detail page
|
||||
|
@ -30,7 +32,7 @@ Feature: dc / intentions / deleting: Deleting items with confirmations, success
|
|||
---
|
||||
And I click delete
|
||||
And I click confirmDelete
|
||||
Then a DELETE request was made to "/v1/connect/intentions/exact?source=default%2Fname&destination=default%2Fdestination&dc=datacenter"
|
||||
Then a DELETE request was made to "/v1/connect/intentions/exact?source=default%2Fdefault%2Fname&destination=default%2Fdefault%2Fdestination&dc=datacenter"
|
||||
And "[data-notification]" has the "notification-delete" class
|
||||
And "[data-notification]" has the "success" class
|
||||
Scenario: Deleting an intention from the intention detail page and getting an error
|
||||
|
@ -39,7 +41,7 @@ Feature: dc / intentions / deleting: Deleting items with confirmations, success
|
|||
dc: datacenter
|
||||
intention: ee52203d-989f-4f7a-ab5a-2bef004164ca
|
||||
---
|
||||
Given the url "/v1/connect/intentions/exact?source=default%2Fname&destination=default%2Fdestination&dc=datacenter" responds with a 500 status
|
||||
Given the url "/v1/connect/intentions/exact?source=default%2Fdefault%2Fname&destination=default%2Fdefault%2Fdestination&dc=datacenter" responds with a 500 status
|
||||
And I click delete
|
||||
And I click confirmDelete
|
||||
And "[data-notification]" has the "notification-update" class
|
||||
|
@ -50,7 +52,7 @@ Feature: dc / intentions / deleting: Deleting items with confirmations, success
|
|||
dc: datacenter
|
||||
intention: ee52203d-989f-4f7a-ab5a-2bef004164ca
|
||||
---
|
||||
Given the url "/v1/connect/intentions/exact?source=default%2Fname&destination=default%2Fdestination&dc=datacenter" responds with from yaml
|
||||
Given the url "/v1/connect/intentions/exact?source=default%2Fdefault%2Fname&destination=default%2Fdefault%2Fdestination&dc=datacenter" responds with from yaml
|
||||
---
|
||||
status: 500
|
||||
body: "duplicate intention found:"
|
||||
|
|
|
@ -4,10 +4,12 @@ Feature: dc / intentions / permissions / warn: Intention Permission Warn
|
|||
Given 1 datacenter model with the value "datacenter"
|
||||
And 1 intention model from yaml
|
||||
---
|
||||
SourceNS: default
|
||||
SourceName: web
|
||||
DestinationNS: default
|
||||
DestinationName: db
|
||||
SourceNS: default
|
||||
DestinationNS: default
|
||||
SourcePartition: default
|
||||
DestinationPartition: default
|
||||
Action: ~
|
||||
Permissions:
|
||||
- Action: allow
|
||||
|
@ -28,4 +30,4 @@ Feature: dc / intentions / permissions / warn: Intention Permission Warn
|
|||
And I submit
|
||||
And I see the warning object
|
||||
And I click the warning.confirm object
|
||||
Then a PUT request was made to "/v1/connect/intentions/exact?source=default%2Fweb&destination=default%2Fdb&dc=datacenter" from yaml
|
||||
Then a PUT request was made to "/v1/connect/intentions/exact?source=default%2Fdefault%2Fweb&destination=default%2Fdefault%2Fdb&dc=datacenter" from yaml
|
||||
|
|
|
@ -4,10 +4,12 @@ Feature: dc / intentions / update: Intention Update
|
|||
Given 1 datacenter model with the value "datacenter"
|
||||
And 1 intention model from yaml
|
||||
---
|
||||
SourceNS: default
|
||||
SourceName: web
|
||||
DestinationNS: default
|
||||
DestinationName: db
|
||||
SourceNS: default
|
||||
DestinationNS: default
|
||||
SourcePartition: default
|
||||
DestinationPartition: default
|
||||
ID: intention-id
|
||||
---
|
||||
When I visit the intention page for yaml
|
||||
|
@ -24,7 +26,7 @@ Feature: dc / intentions / update: Intention Update
|
|||
---
|
||||
And I click "[value=[Action]]"
|
||||
And I submit
|
||||
Then a PUT request was made to "/v1/connect/intentions/exact?source=default%2Fweb&destination=default%2Fdb&dc=datacenter" from yaml
|
||||
Then a PUT request was made to "/v1/connect/intentions/exact?source=default%2Fdefault%2Fweb&destination=default%2Fdefault%2Fdb&dc=datacenter" from yaml
|
||||
---
|
||||
Description: [Description]
|
||||
Action: [Action]
|
||||
|
@ -39,7 +41,7 @@ Feature: dc / intentions / update: Intention Update
|
|||
| Desc | allow |
|
||||
------------------------------
|
||||
Scenario: There was an error saving the intention
|
||||
Given the url "/v1/connect/intentions/exact?source=default%2Fweb&destination=default%2Fdb&dc=datacenter" responds with a 500 status
|
||||
Given the url "/v1/connect/intentions/exact?source=default%2Fdefault%2Fweb&destination=default%2Fdefault%2Fdb&dc=datacenter" responds with a 500 status
|
||||
And I submit
|
||||
Then the url should be /datacenter/intentions/intention-id
|
||||
Then "[data-notification]" has the "notification-update" class
|
||||
|
|
|
@ -15,10 +15,12 @@ Feature: dc / services / show / intentions: Intentions per service
|
|||
- ID: 755b72bd-f5ab-4c92-90cc-bed0e7d8e9f0
|
||||
Action: allow
|
||||
Meta: ~
|
||||
SourceNS: default
|
||||
SourceName: name
|
||||
DestinationNS: default
|
||||
DestinationName: destination
|
||||
SourceNS: default
|
||||
DestinationNS: default
|
||||
SourcePartition: default
|
||||
DestinationPartition: default
|
||||
|
||||
- ID: 755b72bd-f5ab-4c92-90cc-bed0e7d8e9f1
|
||||
Action: deny
|
||||
|
@ -39,11 +41,11 @@ Feature: dc / services / show / intentions: Intentions per service
|
|||
Scenario: I can see intentions
|
||||
And I see 3 intention models on the intentionList component
|
||||
And I click intention on the intentionList.intentions component
|
||||
Then the url should be /dc1/services/service-0/intentions/default:name:default:destination
|
||||
Then the url should be /dc1/services/service-0/intentions/default:default:name:default:default:destination
|
||||
Scenario: I can delete intentions
|
||||
And I click actions on the intentionList.intentions component
|
||||
And I click delete on the intentionList.intentions component
|
||||
And I click confirmDelete on the intentionList.intentions
|
||||
Then a DELETE request was made to "/v1/connect/intentions/exact?source=default%2Fname&destination=default%2Fdestination&dc=dc1"
|
||||
Then a DELETE request was made to "/v1/connect/intentions/exact?source=default%2Fdefault%2Fname&destination=default%2Fdefault%2Fdestination&dc=dc1"
|
||||
And "[data-notification]" has the "notification-delete" class
|
||||
And "[data-notification]" has the "success" class
|
||||
|
|
|
@ -7,7 +7,8 @@ const nspaceRunner = getNspaceRunner('intention');
|
|||
module('Integration | Adapter | intention', function(hooks) {
|
||||
setupTest(hooks);
|
||||
const dc = 'dc-1';
|
||||
const id = 'SourceNS:SourceName:DestinationNS:DestinationName';
|
||||
const id =
|
||||
'SourcePartition:SourceNS:SourceName:DestinationPartition:DestinationNS:DestinationName';
|
||||
test('requestForQuery returns the correct url', function(assert) {
|
||||
return nspaceRunner(
|
||||
(adapter, serializer, client) => {
|
||||
|
@ -15,6 +16,7 @@ module('Integration | Adapter | intention', function(hooks) {
|
|||
return adapter.requestForQuery(request, {
|
||||
dc: dc,
|
||||
ns: 'team-1',
|
||||
partition: 'partition-1',
|
||||
filter: '*',
|
||||
index: 1,
|
||||
});
|
||||
|
@ -23,6 +25,7 @@ module('Integration | Adapter | intention', function(hooks) {
|
|||
filter: '*',
|
||||
index: 1,
|
||||
ns: '*',
|
||||
partition: '*',
|
||||
},
|
||||
{
|
||||
filter: '*',
|
||||
|
@ -36,7 +39,7 @@ module('Integration | Adapter | intention', function(hooks) {
|
|||
const adapter = this.owner.lookup('adapter:intention');
|
||||
const client = this.owner.lookup('service:client/http');
|
||||
const request = client.url.bind(client);
|
||||
const expected = `GET /v1/connect/intentions/exact?source=SourceNS%2FSourceName&destination=DestinationNS%2FDestinationName&dc=${dc}`;
|
||||
const expected = `GET /v1/connect/intentions/exact?source=SourcePartition%2FSourceNS%2FSourceName&destination=DestinationPartition%2FDestinationNS%2FDestinationName&dc=${dc}`;
|
||||
const actual = adapter
|
||||
.requestForQueryRecord(request, {
|
||||
dc: dc,
|
||||
|
@ -59,17 +62,19 @@ module('Integration | Adapter | intention', function(hooks) {
|
|||
const adapter = this.owner.lookup('adapter:intention');
|
||||
const client = this.owner.lookup('service:client/http');
|
||||
const request = client.url.bind(client);
|
||||
const expected = `PUT /v1/connect/intentions/exact?source=SourceNS%2FSourceName&destination=DestinationNS%2FDestinationName&dc=${dc}`;
|
||||
const expected = `PUT /v1/connect/intentions/exact?source=SourcePartition%2FSourceNS%2FSourceName&destination=DestinationPartition%2FDestinationNS%2FDestinationName&dc=${dc}`;
|
||||
const actual = adapter
|
||||
.requestForCreateRecord(
|
||||
request,
|
||||
{},
|
||||
{
|
||||
Datacenter: dc,
|
||||
SourceNS: 'SourceNS',
|
||||
SourceName: 'SourceName',
|
||||
DestinationNS: 'DestinationNS',
|
||||
DestinationName: 'DestinationName',
|
||||
SourceNS: 'SourceNS',
|
||||
DestinationNS: 'DestinationNS',
|
||||
SourcePartition: 'SourcePartition',
|
||||
DestinationPartition: 'DestinationPartition',
|
||||
}
|
||||
)
|
||||
.split('\n')[0];
|
||||
|
@ -79,17 +84,19 @@ module('Integration | Adapter | intention', function(hooks) {
|
|||
const adapter = this.owner.lookup('adapter:intention');
|
||||
const client = this.owner.lookup('service:client/http');
|
||||
const request = client.url.bind(client);
|
||||
const expected = `PUT /v1/connect/intentions/exact?source=SourceNS%2FSourceName&destination=DestinationNS%2FDestinationName&dc=${dc}`;
|
||||
const expected = `PUT /v1/connect/intentions/exact?source=SourcePartition%2FSourceNS%2FSourceName&destination=DestinationPartition%2FDestinationNS%2FDestinationName&dc=${dc}`;
|
||||
const actual = adapter
|
||||
.requestForUpdateRecord(
|
||||
request,
|
||||
{},
|
||||
{
|
||||
Datacenter: dc,
|
||||
SourceNS: 'SourceNS',
|
||||
SourceName: 'SourceName',
|
||||
DestinationNS: 'DestinationNS',
|
||||
DestinationName: 'DestinationName',
|
||||
SourceNS: 'SourceNS',
|
||||
DestinationNS: 'DestinationNS',
|
||||
SourcePartition: 'SourcePartition',
|
||||
DestinationPartition: 'DestinationPartition',
|
||||
}
|
||||
)
|
||||
.split('\n')[0];
|
||||
|
@ -99,17 +106,19 @@ module('Integration | Adapter | intention', function(hooks) {
|
|||
const adapter = this.owner.lookup('adapter:intention');
|
||||
const client = this.owner.lookup('service:client/http');
|
||||
const request = client.url.bind(client);
|
||||
const expected = `DELETE /v1/connect/intentions/exact?source=SourceNS%2FSourceName&destination=DestinationNS%2FDestinationName&dc=${dc}`;
|
||||
const expected = `DELETE /v1/connect/intentions/exact?source=SourcePartition%2FSourceNS%2FSourceName&destination=DestinationPartition%2FDestinationNS%2FDestinationName&dc=${dc}`;
|
||||
const actual = adapter
|
||||
.requestForDeleteRecord(
|
||||
request,
|
||||
{},
|
||||
{
|
||||
Datacenter: dc,
|
||||
SourceNS: 'SourceNS',
|
||||
SourceName: 'SourceName',
|
||||
DestinationNS: 'DestinationNS',
|
||||
DestinationName: 'DestinationName',
|
||||
SourceNS: 'SourceNS',
|
||||
DestinationNS: 'DestinationNS',
|
||||
SourcePartition: 'SourcePartition',
|
||||
DestinationPartition: 'DestinationPartition',
|
||||
}
|
||||
)
|
||||
.split('\n')[0];
|
||||
|
|
|
@ -26,7 +26,7 @@ module('Integration | Serializer | intention', function(hooks) {
|
|||
// refactored out our Serializer this can go
|
||||
Namespace: nspace,
|
||||
Partition: partition,
|
||||
uid: `["${partition}","${nspace}","${dc}","${item.SourceNS}:${item.SourceName}:${item.DestinationNS}:${item.DestinationName}"]`,
|
||||
uid: `["${partition}","${nspace}","${dc}","${item.SourcePartition}:${item.SourceNS}:${item.SourceName}:${item.DestinationPartition}:${item.DestinationNS}:${item.DestinationName}"]`,
|
||||
})
|
||||
);
|
||||
const actual = serializer.respondForQuery(
|
||||
|
@ -55,10 +55,12 @@ module('Integration | Serializer | intention', function(hooks) {
|
|||
url: `/v1/connect/intentions/${id}?dc=${dc}`,
|
||||
};
|
||||
const item = {
|
||||
SourceNS: 'SourceNS',
|
||||
SourceName: 'SourceName',
|
||||
DestinationNS: 'DestinationNS',
|
||||
DestinationName: 'DestinationName',
|
||||
SourceNS: 'SourceNS',
|
||||
DestinationNS: 'DestinationNS',
|
||||
SourcePartition: 'SourcePartition',
|
||||
DestinationPartition: 'DestinationPartition',
|
||||
};
|
||||
return get(request.url).then(function(payload) {
|
||||
payload = {
|
||||
|
@ -76,7 +78,7 @@ module('Integration | Serializer | intention', function(hooks) {
|
|||
// refactored out our Serializer this can go
|
||||
Namespace: nspace,
|
||||
Partition: partition,
|
||||
uid: `["${partition}","${nspace}","${dc}","${item.SourceNS}:${item.SourceName}:${item.DestinationNS}:${item.DestinationName}"]`,
|
||||
uid: `["${partition}","${nspace}","${dc}","${item.SourcePartition}:${item.SourceNS}:${item.SourceName}:${item.DestinationPartition}:${item.DestinationNS}:${item.DestinationName}"]`,
|
||||
});
|
||||
const actual = serializer.respondForQueryRecord(
|
||||
function(cb) {
|
||||
|
|
Loading…
Reference in New Issue