ui: Ensure service instance data does not get re-written on blocking refresh (#11903)
* Add some less fake API data * Rename the models class so as to not be confused with JS Proxies * Rearrange routlets slightly and add some initial outletFor tests * Move away from a MeshChecks computed property and just use a helper * Just use ServiceChecks for healthiness filtering for the moment * Make TProxy cookie configurable * Amend exposed paths and upstreams so they know about meta AND proxy * Slight bit of TaggedAddresses refactor while I was checking for `meta` etc * Document CONSUL_TPROXY_ENABLE
This commit is contained in:
parent
3ab747109b
commit
514e24ba9f
|
@ -0,0 +1,4 @@
|
|||
```release-note:bug
|
||||
ui: Fixes a bug where proxy service health checks would sometimes not appear
|
||||
until refresh
|
||||
```
|
|
@ -28,6 +28,10 @@ export default class Outlet extends Component {
|
|||
return this.args.model || {};
|
||||
}
|
||||
|
||||
get name() {
|
||||
return this.args.name;
|
||||
}
|
||||
|
||||
setAppRoute(name) {
|
||||
if (name !== 'loading' || name === 'oidc-provider-debug') {
|
||||
const doc = this.element.ownerDocument.documentElement;
|
||||
|
@ -55,7 +59,9 @@ export default class Outlet extends Component {
|
|||
}
|
||||
break;
|
||||
case 'model':
|
||||
this.route._model = this.args.model;
|
||||
if(typeof this.route !== 'undefined') {
|
||||
this.route._model = value;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
{{did-insert this.connect}}
|
||||
{{will-destroy this.disconnect}}
|
||||
{{yield (hash
|
||||
model=(or this.model this._model)
|
||||
model=this.model
|
||||
params=this.params
|
||||
currentName=this.router.currentRoute.name
|
||||
|
||||
|
|
|
@ -14,17 +14,14 @@ export default class RouteComponent extends Component {
|
|||
}
|
||||
|
||||
get model() {
|
||||
if(this.args.name) {
|
||||
const temp = this.args.name.split('.');
|
||||
temp.pop();
|
||||
const name = temp.join('.');
|
||||
let model = this.routlet.modelFor(name);
|
||||
if(Object.keys(model).length === 0) {
|
||||
return null;
|
||||
}
|
||||
return model;
|
||||
if(this._model) {
|
||||
return this._model;
|
||||
}
|
||||
return null;
|
||||
if (this.args.name) {
|
||||
const outlet = this.routlet.outletFor(this.args.name);
|
||||
return this.routlet.modelFor(outlet.name);
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
@action
|
||||
|
|
|
@ -5,7 +5,7 @@ export default {
|
|||
passing: (item, value) => item.Status === value,
|
||||
warning: (item, value) => item.Status === value,
|
||||
critical: (item, value) => item.Status === value,
|
||||
empty: (item, value) => item.MeshChecks.length === 0,
|
||||
empty: (item, value) => item.ServiceChecks.length === 0,
|
||||
},
|
||||
source: (item, values) => {
|
||||
return setHelpers.intersectionSize(values, new Set(item.ExternalSources || [])) !== 0;
|
||||
|
|
|
@ -0,0 +1,9 @@
|
|||
import { helper } from '@ember/component/helper';
|
||||
import mergeChecks from 'consul-ui/utils/merge-checks';
|
||||
|
||||
export default helper(function([checks, exposed], hash) {
|
||||
return mergeChecks(
|
||||
checks,
|
||||
exposed
|
||||
);
|
||||
});
|
|
@ -5,7 +5,7 @@ export const PRIMARY_KEY = 'uid';
|
|||
export const SLUG_KEY = 'Node,ServiceID';
|
||||
|
||||
// TODO: This should be changed to ProxyInstance
|
||||
export default class Proxy extends ServiceInstanceModel {
|
||||
export default class ProxyServiceInstance extends ServiceInstanceModel {
|
||||
@attr('string') uid;
|
||||
@attr('string') ID;
|
||||
|
||||
|
|
|
@ -1,9 +1,8 @@
|
|||
import Model, { attr, belongsTo } from '@ember-data/model';
|
||||
import Model, { attr } from '@ember-data/model';
|
||||
import { fragmentArray } from 'ember-data-model-fragments/attributes';
|
||||
import { computed, get } from '@ember/object';
|
||||
import { computed } from '@ember/object';
|
||||
import { or, filter, alias } from '@ember/object/computed';
|
||||
import { tracked } from '@glimmer/tracking';
|
||||
import mergeChecks from 'consul-ui/utils/merge-checks';
|
||||
|
||||
export const PRIMARY_KEY = 'uid';
|
||||
export const SLUG_KEY = 'Node.Node,Service.ID';
|
||||
|
@ -28,8 +27,6 @@ export default class ServiceInstance extends Model {
|
|||
@attr('string') uid;
|
||||
|
||||
@attr('string') Datacenter;
|
||||
// ProxyInstance is the ember-data model relationship
|
||||
@belongsTo('Proxy') ProxyInstance;
|
||||
// Proxy is the actual JSON api response
|
||||
@attr() Proxy;
|
||||
@attr() Node;
|
||||
|
@ -55,18 +52,6 @@ export default class ServiceInstance extends Model {
|
|||
@filter('Checks.@each.Kind', (item, i, arr) => item.Kind === 'service') ServiceChecks;
|
||||
@filter('Checks.@each.Kind', (item, i, arr) => item.Kind === 'node') NodeChecks;
|
||||
|
||||
// MeshChecks are a concatenation of Checks for the Instance and Checks for
|
||||
// the ProxyInstance.
|
||||
@computed('Checks.[]', 'ProxyInstance.{Checks.[],ServiceProxy.Expose.Checks}')
|
||||
get MeshChecks() {
|
||||
// merge the instance and proxy checks together, avoiding duplicate node
|
||||
// checks and additionally setting any checks to exposed if required
|
||||
return mergeChecks(
|
||||
[get(this, 'Checks'), get(this, 'ProxyInstance.Checks')],
|
||||
get(this, 'ProxyInstance.ServiceProxy.Expose.Checks')
|
||||
);
|
||||
}
|
||||
|
||||
@computed('Service.Meta')
|
||||
get ExternalSources() {
|
||||
const sources = Object.entries(this.Service.Meta || {})
|
||||
|
|
|
@ -36,24 +36,24 @@ export default class ProxyService extends RepositoryService {
|
|||
}
|
||||
|
||||
@dataSource('/:partition/:ns/:dc/proxy-instance/:serviceId/:node/:id')
|
||||
findInstanceBySlug(params, configuration) {
|
||||
return this.findAllBySlug(params, configuration).then(function(items) {
|
||||
let res = {};
|
||||
if (get(items, 'length') > 0) {
|
||||
let instance = items
|
||||
.filterBy('ServiceProxy.DestinationServiceID', params.serviceId)
|
||||
.findBy('NodeName', params.node);
|
||||
async findInstanceBySlug(params, configuration) {
|
||||
const items = await this.findAllBySlug(params, configuration);
|
||||
|
||||
let res = {};
|
||||
if (get(items, 'length') > 0) {
|
||||
let instance = items
|
||||
.filterBy('ServiceProxy.DestinationServiceID', params.serviceId)
|
||||
.findBy('NodeName', params.node);
|
||||
if (instance) {
|
||||
res = instance;
|
||||
} else {
|
||||
instance = items.findBy('ServiceProxy.DestinationServiceName', params.id);
|
||||
if (instance) {
|
||||
res = instance;
|
||||
} else {
|
||||
instance = items.findBy('ServiceProxy.DestinationServiceName', params.id);
|
||||
if (instance) {
|
||||
res = instance;
|
||||
}
|
||||
}
|
||||
}
|
||||
set(res, 'meta', get(items, 'meta'));
|
||||
return res;
|
||||
});
|
||||
}
|
||||
set(res, 'meta', get(items, 'meta'));
|
||||
return res;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,12 +1,10 @@
|
|||
import RepositoryService from 'consul-ui/services/repository';
|
||||
import { inject as service } from '@ember/service';
|
||||
import { set } from '@ember/object';
|
||||
import { ACCESS_READ } from 'consul-ui/abilities/base';
|
||||
import dataSource from 'consul-ui/decorators/data-source';
|
||||
|
||||
const modelName = 'service-instance';
|
||||
export default class ServiceInstanceService extends RepositoryService {
|
||||
@service('repository/proxy') proxyRepo;
|
||||
getModelName() {
|
||||
return modelName;
|
||||
}
|
||||
|
@ -34,44 +32,6 @@ export default class ServiceInstanceService extends RepositoryService {
|
|||
|
||||
@dataSource('/:partition/:ns/:dc/service-instance/:serviceId/:node/:id')
|
||||
async findBySlug(params, configuration = {}) {
|
||||
if (typeof configuration.cursor !== 'undefined') {
|
||||
params.index = configuration.cursor;
|
||||
params.uri = configuration.uri;
|
||||
}
|
||||
return this.authorizeBySlug(
|
||||
async () => this.store.queryRecord(this.getModelName(), params),
|
||||
ACCESS_READ,
|
||||
params
|
||||
);
|
||||
}
|
||||
|
||||
@dataSource('/:partition/:ns/:dc/proxy-service-instance/:serviceId/:node/:id')
|
||||
async findProxyBySlug(params, configuration = {}) {
|
||||
const instance = await this.findBySlug(...arguments);
|
||||
let proxy = this.store.peekRecord('proxy', instance.uid);
|
||||
// Currently, we call the proxy endpoint before this endpoint
|
||||
// therefore proxy is never undefined. If we ever call this endpoint
|
||||
// first we'll need to do something like the following
|
||||
// if(typeof proxy === 'undefined') {
|
||||
// await proxyRepo.create({})
|
||||
// }
|
||||
|
||||
// Copy over all the things to the ProxyServiceInstance
|
||||
['Service', 'Node', 'meta'].forEach(prop => {
|
||||
set(proxy, prop, instance[prop]);
|
||||
});
|
||||
['Checks'].forEach(prop => {
|
||||
// completely wipe out any previous values so we don't accumulate things
|
||||
// eternally
|
||||
proxy.set(prop, []);
|
||||
instance[prop].forEach(item => {
|
||||
if (typeof item !== 'undefined') {
|
||||
proxy[prop].addFragment(item.copy());
|
||||
}
|
||||
});
|
||||
});
|
||||
// delete the ServiceInstance record as we now have a ProxyServiceInstance
|
||||
instance.unloadRecord();
|
||||
return proxy;
|
||||
return super.findBySlug(...arguments);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -75,21 +75,11 @@ export default class RoutletService extends Service {
|
|||
return key;
|
||||
}
|
||||
|
||||
addOutlet(name, outlet) {
|
||||
outlets.set(name, outlet);
|
||||
}
|
||||
|
||||
removeOutlet(name) {
|
||||
outlets.delete(name);
|
||||
}
|
||||
|
||||
// modelFor gets the model for Outlet specified by `name`, not the Route
|
||||
modelFor(name) {
|
||||
const outlet = outlets.get(name);
|
||||
if (typeof outlet !== 'undefined') {
|
||||
return outlet.model || {};
|
||||
}
|
||||
return {};
|
||||
outletFor(routeName) {
|
||||
const keys = [...outlets.keys()];
|
||||
const pos = keys.indexOf(routeName);
|
||||
const key = pos + 1;
|
||||
return outlets.get(keys[key]);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -149,20 +139,43 @@ export default class RoutletService extends Service {
|
|||
};
|
||||
}
|
||||
|
||||
addRoute(name, route) {
|
||||
const keys = [...outlets.keys()];
|
||||
const pos = keys.indexOf(name);
|
||||
const key = pos + 1;
|
||||
const outlet = outlets.get(keys[key]);
|
||||
|
||||
// modelFor gets the model for Outlet specified by `name`, not the Route
|
||||
modelFor(name) {
|
||||
const outlet = outlets.get(name);
|
||||
if (typeof outlet !== 'undefined') {
|
||||
return outlet.model;
|
||||
}
|
||||
}
|
||||
|
||||
addRoute(name, route) {
|
||||
const outlet = this.outletFor(name);
|
||||
if (typeof outlet !== 'undefined') {
|
||||
route._model = outlet.model;
|
||||
outlet.route = route;
|
||||
// TODO: Try to avoid the double computation bug
|
||||
schedule('afterRender', () => {
|
||||
outlet.routeName = route.args.name;
|
||||
outlet.routeName = name;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
removeRoute(name, route) {}
|
||||
removeRoute(name, route) {
|
||||
const outlet = this.outletFor(name);
|
||||
route._model = undefined;
|
||||
if (typeof outlet !== 'undefined') {
|
||||
schedule('afterRender', () => {
|
||||
outlet.route = undefined;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
addOutlet(name, outlet) {
|
||||
outlets.set(name, outlet);
|
||||
}
|
||||
|
||||
removeOutlet(name) {
|
||||
schedule('afterRender', () => {
|
||||
outlets.delete(name);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -94,6 +94,7 @@ as |item|}}
|
|||
name=route.params.name
|
||||
)
|
||||
}}
|
||||
@onchange={{action (mut meta) value="data"}}
|
||||
as |meta|>
|
||||
{{! We only really need meta to get the correct ServiceID }}
|
||||
{{! but we may as well use the NodeName and ServiceName }}
|
||||
|
@ -101,8 +102,13 @@ as |item|}}
|
|||
{{! so if we can ever get ServiceID from elsewhere we could save }}
|
||||
{{! a HTTP request/long poll here }}
|
||||
{{#if meta.data.ServiceID}}
|
||||
{{! if we have a proxy then get the additional instance information }}
|
||||
{{! for the proxy itself so if the service is called `backend` }}
|
||||
{{! its likely to have a proxy service called `backend-sidecar-proxy` }}
|
||||
{{! and this second request get the info for that instance and saves }}
|
||||
{{! it into the `proxy` variable }}
|
||||
<DataSource
|
||||
@src={{uri '/${partition}/${nspace}/${dc}/proxy-service-instance/${id}/${node}/${name}'
|
||||
@src={{uri '/${partition}/${nspace}/${dc}/service-instance/${id}/${node}/${name}'
|
||||
(hash
|
||||
partition=route.params.partition
|
||||
nspace=route.params.nspace
|
||||
|
@ -112,7 +118,8 @@ as |item|}}
|
|||
name=meta.data.ServiceName
|
||||
)
|
||||
}}
|
||||
@onchange={{action (mut proxy) value="data"}}/>
|
||||
@onchange={{action (mut proxy) value="data"}}
|
||||
/>
|
||||
{{/if}}
|
||||
</DataSource>
|
||||
{{/if}}
|
||||
|
@ -129,7 +136,9 @@ as |item|}}
|
|||
</h1>
|
||||
<Consul::ExternalSource @item={{item}} @withInfo={{true}} />
|
||||
<Consul::Kind @item={{item}} @withInfo={{true}} />
|
||||
{{#if (eq proxy.ServiceProxy.Mode 'transparent')}}
|
||||
{{! TODO: Looks like we can get this straight from item.Proxy.Mode }}
|
||||
{{! the less we need `proxy` and `meta` the better }}
|
||||
{{#if (eq meta.ServiceProxy.Mode 'transparent')}}
|
||||
<Consul::TransparentProxy />
|
||||
{{/if}}
|
||||
</BlockSlot>
|
||||
|
@ -149,27 +158,22 @@ as |item|}}
|
|||
{{/let}}
|
||||
</BlockSlot>
|
||||
<BlockSlot @name="content">
|
||||
<TabNav @items={{
|
||||
compact
|
||||
(array
|
||||
(hash label="Health Checks" href=(href-to "dc.services.instance.healthchecks") selected=(is-href "dc.services.instance.healthchecks"))
|
||||
(if
|
||||
(eq item.Service.Kind 'mesh-gateway')
|
||||
(hash label="Addresses" href=(href-to "dc.services.instance.addresses") selected=(is-href "dc.services.instance.addresses")) ""
|
||||
)
|
||||
(if proxy
|
||||
(hash label="Upstreams" href=(href-to "dc.services.instance.upstreams") selected=(is-href "dc.services.instance.upstreams"))
|
||||
)
|
||||
(if proxy
|
||||
(hash label="Exposed Paths" href=(href-to "dc.services.instance.exposedpaths") selected=(is-href "dc.services.instance.exposedpaths"))
|
||||
)
|
||||
(hash label="Tags & Meta" href=(href-to "dc.services.instance.metadata") selected=(is-href "dc.services.instance.metadata"))
|
||||
)
|
||||
}}/>
|
||||
<TabNav @items={{
|
||||
compact
|
||||
(array
|
||||
(hash label="Health Checks" href=(href-to "dc.services.instance.healthchecks") selected=(is-href "dc.services.instance.healthchecks"))
|
||||
(if (eq item.Service.Kind 'mesh-gateway') (hash label="Addresses" href=(href-to "dc.services.instance.addresses") selected=(is-href "dc.services.instance.addresses")))
|
||||
(if proxy (hash label="Upstreams" href=(href-to "dc.services.instance.upstreams") selected=(is-href "dc.services.instance.upstreams")))
|
||||
(if proxy (hash label="Exposed Paths" href=(href-to "dc.services.instance.exposedpaths") selected=(is-href "dc.services.instance.exposedpaths")))
|
||||
(hash label="Tags & Meta" href=(href-to "dc.services.instance.metadata") selected=(is-href "dc.services.instance.metadata"))
|
||||
)
|
||||
}}
|
||||
/>
|
||||
<Outlet
|
||||
@name={{routeName}}
|
||||
@model={{assign (hash
|
||||
proxy=proxy
|
||||
meta=meta
|
||||
item=item
|
||||
) route.model}}
|
||||
as |o|>
|
||||
|
|
|
@ -2,14 +2,14 @@
|
|||
@name={{routeName}}
|
||||
as |route|>
|
||||
{{#let
|
||||
route.model.item
|
||||
as |item|}}
|
||||
(entries route.model.item.Service.TaggedAddresses)
|
||||
as |items|}}
|
||||
<div class="tab-section">
|
||||
{{#if item.Service.TaggedAddresses }}
|
||||
{{#if (gt items.length 0)}}
|
||||
<TabularCollection
|
||||
data-test-addresses
|
||||
class="consul-tagged-addresses"
|
||||
@items={{entries item.Service.TaggedAddresses}} as |taggedAddress index|
|
||||
@items={{items}} as |taggedAddress index|
|
||||
>
|
||||
<BlockSlot @name="header">
|
||||
<th>Tag</th>
|
||||
|
|
|
@ -3,13 +3,17 @@
|
|||
as |route|>
|
||||
{{#let
|
||||
route.model.proxy
|
||||
as |proxy|}}
|
||||
route.model.meta
|
||||
as |item proxy|}}
|
||||
<div class="tab-section">
|
||||
{{#if (gt proxy.Service.Proxy.Expose.Paths.length 0)}}
|
||||
{{#if (gt proxy.ServiceProxy.Expose.Paths.length 0)}}
|
||||
<p>
|
||||
The following list shows individual HTTP paths exposed through Envoy for external services like Prometheus. Read more about this in our documentation.
|
||||
The following list shows individual HTTP paths exposed through Envoy for external services like Prometheus. Read more about this in our <Action @href={{concat (env 'CONSUL_DOCS_URL') '/connect/registration/service-registration#expose-paths-configuration-reference'}} @external={{true}}>documentation</Action>.
|
||||
</p>
|
||||
<Consul::ExposedPath::List @items={{proxy.Service.Proxy.Expose.Paths}} @address={{proxy.Address}} />
|
||||
<Consul::ExposedPath::List
|
||||
@items={{proxy.ServiceProxy.Expose.Paths}}
|
||||
@address={{or item.Service.Address item.Node.Address}}
|
||||
/>
|
||||
{{else}}
|
||||
<EmptyState>
|
||||
<BlockSlot @name="body">
|
||||
|
|
|
@ -27,7 +27,7 @@ as |route|>
|
|||
)
|
||||
)
|
||||
|
||||
route.model.item.MeshChecks
|
||||
(merge-checks (array route.model.item.Checks route.model.proxy.Checks) route.model.proxy.ServiceProxy.Expose.Checks)
|
||||
|
||||
as |sort filters items|}}
|
||||
<div class="tab-section">
|
||||
|
|
|
@ -25,9 +25,10 @@ as |route|>
|
|||
route.params.dc
|
||||
|
||||
route.model.proxy
|
||||
route.model.meta
|
||||
route.model.proxy.Service.Proxy.Upstreams
|
||||
|
||||
as |sort filters partition nspace dc proxy items|}}
|
||||
as |sort filters partition nspace dc proxy meta items|}}
|
||||
{{#if (gt items.length 0)}}
|
||||
<input type="checkbox" id="toolbar-toggle" />
|
||||
<Consul::UpstreamInstance::SearchBar
|
||||
|
@ -40,29 +41,33 @@ as |route|>
|
|||
@filter={{filters}}
|
||||
/>
|
||||
{{/if}}
|
||||
{{#if (eq proxy.ServiceProxy.Mode 'transparent')}}
|
||||
<Notice
|
||||
@type="warning"
|
||||
as |notice|>
|
||||
<notice.Header>
|
||||
<h3>{{t "routes.dc.services.instance.upstreams.tproxy-mode.header"}}</h3>
|
||||
</notice.Header>
|
||||
<notice.Body>
|
||||
<p>
|
||||
{{t "routes.dc.services.instance.upstreams.tproxy-mode.body"}}
|
||||
</p>
|
||||
</notice.Body>
|
||||
<notice.Footer>
|
||||
<p>
|
||||
<Action
|
||||
@href={{concat (env 'CONSUL_DOCS_URL') '/connect/transparent-proxy'}}
|
||||
@external={{true}}
|
||||
>
|
||||
{{t "routes.dc.services.instance.upstreams.tproxy-mode.footer"}}
|
||||
</Action>
|
||||
</p>
|
||||
</notice.Footer>
|
||||
</Notice>
|
||||
{{! TODO: Looks like we can get this straight from item.Proxy.Mode }}
|
||||
{{! the less we need `proxy` and `meta` the better }}
|
||||
{{#if (eq meta.ServiceProxy.Mode 'transparent')}}
|
||||
<Notice
|
||||
@type="warning"
|
||||
as |notice|>
|
||||
<notice.Header>
|
||||
<h3>
|
||||
{{t "routes.dc.services.instance.upstreams.tproxy-mode.header"}}
|
||||
</h3>
|
||||
</notice.Header>
|
||||
<notice.Body>
|
||||
<p>
|
||||
{{t "routes.dc.services.instance.upstreams.tproxy-mode.body"}}
|
||||
</p>
|
||||
</notice.Body>
|
||||
<notice.Footer>
|
||||
<p>
|
||||
<Action
|
||||
@href={{concat (env 'CONSUL_DOCS_URL') '/connect/transparent-proxy'}}
|
||||
@external={{true}}
|
||||
>
|
||||
{{t "routes.dc.services.instance.upstreams.tproxy-mode.footer"}}
|
||||
</Action>
|
||||
</p>
|
||||
</notice.Footer>
|
||||
</Notice>
|
||||
{{/if}}
|
||||
<DataCollection
|
||||
@type="upstream-instance"
|
||||
|
|
|
@ -9,6 +9,7 @@ Below is a list of the most commonly used functions as bookmarklets followed by
|
|||
| [Print Routing DSL](javascript:Routes()) | Print out Ember's Route DSL for the application |
|
||||
| [Save Current Scenario](javascript:Scenario()) | Opens a tab with links to allow you to create a bookmarklet or share a URL of your current scenario (your Consul UI relarted development/debug cookies) |
|
||||
| [Enable ACLs](javascript:Scenario('CONSUL_ACLS_ENABLE=1')) | Enable ACLs |
|
||||
| [Enable TProxy](javascript:Scenario('CONSUL_TPROXY_ENABLE=1')) | Enable TProxy |
|
||||
| [Enable Nspaces](javascript:Scenario('CONSUL_NSPACES_ENABLE=1')) | Enable Namespace Support |
|
||||
| [Enable Partitions](javascript:Scenario('CONSUL_PARTITIONS_ENABLE=1')) | Enable Admin Partition Support |
|
||||
| [Enable SSO](javascript:Scenario('CONSUL_SSO_ENABLE=1')) | Enable SSO Support |
|
||||
|
@ -37,6 +38,7 @@ token/secret.
|
|||
| -------- | ------------- | ----------- |
|
||||
| `CONSUL_ACLS_ENABLE` | false | Enable/disable ACLs support. |
|
||||
| `CONSUL_ACLS_LEGACY` | false | Enable/disable legacy ACLs support. |
|
||||
| `CONSUL_TPROXY_ENABLE` | false | Enable/disable TProxy support globally (if not a service may have this applied randomly). |
|
||||
| `CONSUL_NSPACES_ENABLE` | false | Enable/disable Namespace support. |
|
||||
| `CONSUL_SSO_ENABLE` | false | Enable/disable SSO support. |
|
||||
| `CONSUL_OIDC_PROVIDER_URL` | undefined | Provide a OIDC provider URL for SSO. |
|
||||
|
|
|
@ -52,7 +52,7 @@ ${range(env('CONSUL_EXPOSED_COUNT', 3)).map((i) => `
|
|||
`)}
|
||||
]
|
||||
},
|
||||
"Mode": "${fake.helpers.randomize(['', 'direct', 'transparent'])}",
|
||||
"Mode": "${env('CONSUL_TPROXY_ENABLE') ? `transparent` : fake.helpers.randomize(['', 'direct', 'transparent'])}",
|
||||
"TransparentProxy": {},
|
||||
"DestinationServiceName": "${location.pathname.slice(4)}"
|
||||
${ location.pathname.slice(4) === "service-0" ? `
|
||||
|
|
|
@ -0,0 +1,82 @@
|
|||
[
|
||||
{
|
||||
"ID": "237b9eeb-bba1-e6e3-3c99-c527d6d76cc0",
|
||||
"Node": "node",
|
||||
"Address": "172.17.0.2",
|
||||
"Datacenter": "dc1",
|
||||
"TaggedAddresses": {
|
||||
"lan": "172.17.0.2",
|
||||
"lan_ipv4": "172.17.0.2",
|
||||
"wan": "172.17.0.2",
|
||||
"wan_ipv4": "172.17.0.2"
|
||||
},
|
||||
"NodeMeta": {
|
||||
"consul-network-segment": ""
|
||||
},
|
||||
"ServiceKind": "connect-proxy",
|
||||
"ServiceID": "backend-sidecar-proxy",
|
||||
"ServiceName": "backend-sidecar-proxy",
|
||||
"ServiceTags": [],
|
||||
"ServiceAddress": "",
|
||||
"ServiceWeights": {
|
||||
"Passing": 1,
|
||||
"Warning": 1
|
||||
},
|
||||
"ServiceMeta": {},
|
||||
"ServicePort": 21000,
|
||||
"ServiceSocketPath": "",
|
||||
"ServiceEnableTagOverride": false,
|
||||
"ServiceProxy": {
|
||||
"DestinationServiceName": "backend",
|
||||
"DestinationServiceID": "backend",
|
||||
"LocalServiceAddress": "127.0.0.1",
|
||||
"LocalServicePort": 7000,
|
||||
"Mode": "",
|
||||
"MeshGateway": {},
|
||||
"Expose": {}
|
||||
},
|
||||
"ServiceConnect": {},
|
||||
"CreateIndex": 19,
|
||||
"ModifyIndex": 19
|
||||
},
|
||||
{
|
||||
"ID": "237b9eeb-bba1-e6e3-3c99-c527d6d76cc0",
|
||||
"Node": "node",
|
||||
"Address": "172.17.0.2",
|
||||
"Datacenter": "dc1",
|
||||
"TaggedAddresses": {
|
||||
"lan": "172.17.0.2",
|
||||
"lan_ipv4": "172.17.0.2",
|
||||
"wan": "172.17.0.2",
|
||||
"wan_ipv4": "172.17.0.2"
|
||||
},
|
||||
"NodeMeta": {
|
||||
"consul-network-segment": ""
|
||||
},
|
||||
"ServiceKind": "connect-proxy",
|
||||
"ServiceID": "backend-v2-sidecar-proxy",
|
||||
"ServiceName": "backend-sidecar-proxy",
|
||||
"ServiceTags": [],
|
||||
"ServiceAddress": "",
|
||||
"ServiceWeights": {
|
||||
"Passing": 1,
|
||||
"Warning": 1
|
||||
},
|
||||
"ServiceMeta": {},
|
||||
"ServicePort": 21001,
|
||||
"ServiceSocketPath": "",
|
||||
"ServiceEnableTagOverride": false,
|
||||
"ServiceProxy": {
|
||||
"DestinationServiceName": "backend",
|
||||
"DestinationServiceID": "backend-v2",
|
||||
"LocalServiceAddress": "127.0.0.1",
|
||||
"LocalServicePort": 7001,
|
||||
"Mode": "",
|
||||
"MeshGateway": {},
|
||||
"Expose": {}
|
||||
},
|
||||
"ServiceConnect": {},
|
||||
"CreateIndex": 21,
|
||||
"ModifyIndex": 21
|
||||
}
|
||||
]
|
|
@ -0,0 +1,122 @@
|
|||
[
|
||||
{
|
||||
"Node": {
|
||||
"ID": "237b9eeb-bba1-e6e3-3c99-c527d6d76cc0",
|
||||
"Node": "node",
|
||||
"Address": "172.17.0.2",
|
||||
"Datacenter": "dc1",
|
||||
"TaggedAddresses": {
|
||||
"lan": "172.17.0.2",
|
||||
"lan_ipv4": "172.17.0.2",
|
||||
"wan": "172.17.0.2",
|
||||
"wan_ipv4": "172.17.0.2"
|
||||
},
|
||||
"Meta": {
|
||||
"consul-network-segment": ""
|
||||
},
|
||||
"CreateIndex": 14,
|
||||
"ModifyIndex": 17
|
||||
},
|
||||
"Service": {
|
||||
"ID": "backend",
|
||||
"Service": "backend",
|
||||
"Tags": [],
|
||||
"Address": "",
|
||||
"Meta": null,
|
||||
"Port": 7000,
|
||||
"Weights": {
|
||||
"Passing": 1,
|
||||
"Warning": 1
|
||||
},
|
||||
"EnableTagOverride": false,
|
||||
"Proxy": {
|
||||
"Mode": "",
|
||||
"MeshGateway": {},
|
||||
"Expose": {}
|
||||
},
|
||||
"Connect": {},
|
||||
"CreateIndex": 18,
|
||||
"ModifyIndex": 18
|
||||
},
|
||||
"Checks": [
|
||||
{
|
||||
"Node": "node",
|
||||
"CheckID": "serfHealth",
|
||||
"Name": "Serf Health Status",
|
||||
"Status": "passing",
|
||||
"Notes": "",
|
||||
"Output": "Agent alive and reachable",
|
||||
"ServiceID": "",
|
||||
"ServiceName": "",
|
||||
"ServiceTags": [],
|
||||
"Type": "",
|
||||
"Interval": "",
|
||||
"Timeout": "",
|
||||
"ExposedPort": 0,
|
||||
"Definition": {},
|
||||
"CreateIndex": 14,
|
||||
"ModifyIndex": 14
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"Node": {
|
||||
"ID": "237b9eeb-bba1-e6e3-3c99-c527d6d76cc0",
|
||||
"Node": "node",
|
||||
"Address": "172.17.0.2",
|
||||
"Datacenter": "dc1",
|
||||
"TaggedAddresses": {
|
||||
"lan": "172.17.0.2",
|
||||
"lan_ipv4": "172.17.0.2",
|
||||
"wan": "172.17.0.2",
|
||||
"wan_ipv4": "172.17.0.2"
|
||||
},
|
||||
"Meta": {
|
||||
"consul-network-segment": ""
|
||||
},
|
||||
"CreateIndex": 14,
|
||||
"ModifyIndex": 17
|
||||
},
|
||||
"Service": {
|
||||
"ID": "backend-v2",
|
||||
"Service": "backend",
|
||||
"Tags": [],
|
||||
"Address": "",
|
||||
"Meta": null,
|
||||
"Port": 7001,
|
||||
"Weights": {
|
||||
"Passing": 1,
|
||||
"Warning": 1
|
||||
},
|
||||
"EnableTagOverride": false,
|
||||
"Proxy": {
|
||||
"Mode": "",
|
||||
"MeshGateway": {},
|
||||
"Expose": {}
|
||||
},
|
||||
"Connect": {},
|
||||
"CreateIndex": 20,
|
||||
"ModifyIndex": 20
|
||||
},
|
||||
"Checks": [
|
||||
{
|
||||
"Node": "node",
|
||||
"CheckID": "serfHealth",
|
||||
"Name": "Serf Health Status",
|
||||
"Status": "passing",
|
||||
"Notes": "",
|
||||
"Output": "Agent alive and reachable",
|
||||
"ServiceID": "",
|
||||
"ServiceName": "",
|
||||
"ServiceTags": [],
|
||||
"Type": "",
|
||||
"Interval": "",
|
||||
"Timeout": "",
|
||||
"ExposedPort": 0,
|
||||
"Definition": {},
|
||||
"CreateIndex": 14,
|
||||
"ModifyIndex": 14
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
|
@ -0,0 +1,204 @@
|
|||
[
|
||||
{
|
||||
"Node": {
|
||||
"ID": "237b9eeb-bba1-e6e3-3c99-c527d6d76cc0",
|
||||
"Node": "node",
|
||||
"Address": "172.17.0.2",
|
||||
"Datacenter": "dc1",
|
||||
"TaggedAddresses": {
|
||||
"lan": "172.17.0.2",
|
||||
"lan_ipv4": "172.17.0.2",
|
||||
"wan": "172.17.0.2",
|
||||
"wan_ipv4": "172.17.0.2"
|
||||
},
|
||||
"Meta": {
|
||||
"consul-network-segment": ""
|
||||
},
|
||||
"CreateIndex": 14,
|
||||
"ModifyIndex": 17
|
||||
},
|
||||
"Service": {
|
||||
"Kind": "connect-proxy",
|
||||
"ID": "backend-sidecar-proxy",
|
||||
"Service": "backend-sidecar-proxy",
|
||||
"Tags": [],
|
||||
"Address": "",
|
||||
"Meta": null,
|
||||
"Port": 21000,
|
||||
"Weights": {
|
||||
"Passing": 1,
|
||||
"Warning": 1
|
||||
},
|
||||
"EnableTagOverride": false,
|
||||
"Proxy": {
|
||||
"DestinationServiceName": "backend",
|
||||
"DestinationServiceID": "backend",
|
||||
"LocalServiceAddress": "127.0.0.1",
|
||||
"LocalServicePort": 7000,
|
||||
"Mode": "",
|
||||
"MeshGateway": {},
|
||||
"Expose": {}
|
||||
},
|
||||
"Connect": {},
|
||||
"CreateIndex": 19,
|
||||
"ModifyIndex": 19
|
||||
},
|
||||
"Checks": [
|
||||
{
|
||||
"Node": "node",
|
||||
"CheckID": "serfHealth",
|
||||
"Name": "Serf Health Status",
|
||||
"Status": "passing",
|
||||
"Notes": "",
|
||||
"Output": "Agent alive and reachable",
|
||||
"ServiceID": "",
|
||||
"ServiceName": "",
|
||||
"ServiceTags": [],
|
||||
"Type": "",
|
||||
"Interval": "",
|
||||
"Timeout": "",
|
||||
"ExposedPort": 0,
|
||||
"Definition": {},
|
||||
"CreateIndex": 14,
|
||||
"ModifyIndex": 14
|
||||
},
|
||||
{
|
||||
"Node": "node",
|
||||
"CheckID": "service:backend-sidecar-proxy:1",
|
||||
"Name": "Connect Sidecar Listening",
|
||||
"Status": "critical",
|
||||
"Notes": "",
|
||||
"Output": "dial tcp 127.0.0.1:21000: connect: connection refused",
|
||||
"ServiceID": "backend-sidecar-proxy",
|
||||
"ServiceName": "backend-sidecar-proxy",
|
||||
"ServiceTags": [],
|
||||
"Type": "tcp",
|
||||
"Interval": "",
|
||||
"Timeout": "",
|
||||
"ExposedPort": 0,
|
||||
"Definition": {},
|
||||
"CreateIndex": 19,
|
||||
"ModifyIndex": 42
|
||||
},
|
||||
{
|
||||
"Node": "node",
|
||||
"CheckID": "service:backend-sidecar-proxy:2",
|
||||
"Name": "Connect Sidecar Aliasing backend",
|
||||
"Status": "critical",
|
||||
"Notes": "",
|
||||
"Output": "No checks found.",
|
||||
"ServiceID": "backend-sidecar-proxy",
|
||||
"ServiceName": "backend-sidecar-proxy",
|
||||
"ServiceTags": [],
|
||||
"Type": "alias",
|
||||
"Interval": "",
|
||||
"Timeout": "",
|
||||
"ExposedPort": 0,
|
||||
"Definition": {},
|
||||
"CreateIndex": 19,
|
||||
"ModifyIndex": 19
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"Node": {
|
||||
"ID": "237b9eeb-bba1-e6e3-3c99-c527d6d76cc0",
|
||||
"Node": "node",
|
||||
"Address": "172.17.0.2",
|
||||
"Datacenter": "dc1",
|
||||
"TaggedAddresses": {
|
||||
"lan": "172.17.0.2",
|
||||
"lan_ipv4": "172.17.0.2",
|
||||
"wan": "172.17.0.2",
|
||||
"wan_ipv4": "172.17.0.2"
|
||||
},
|
||||
"Meta": {
|
||||
"consul-network-segment": ""
|
||||
},
|
||||
"CreateIndex": 14,
|
||||
"ModifyIndex": 17
|
||||
},
|
||||
"Service": {
|
||||
"Kind": "connect-proxy",
|
||||
"ID": "backend-v2-sidecar-proxy",
|
||||
"Service": "backend-sidecar-proxy",
|
||||
"Tags": [],
|
||||
"Address": "",
|
||||
"Meta": null,
|
||||
"Port": 21001,
|
||||
"Weights": {
|
||||
"Passing": 1,
|
||||
"Warning": 1
|
||||
},
|
||||
"EnableTagOverride": false,
|
||||
"Proxy": {
|
||||
"DestinationServiceName": "backend",
|
||||
"DestinationServiceID": "backend-v2",
|
||||
"LocalServiceAddress": "127.0.0.1",
|
||||
"LocalServicePort": 7001,
|
||||
"Mode": "",
|
||||
"MeshGateway": {},
|
||||
"Expose": {}
|
||||
},
|
||||
"Connect": {},
|
||||
"CreateIndex": 21,
|
||||
"ModifyIndex": 21
|
||||
},
|
||||
"Checks": [
|
||||
{
|
||||
"Node": "node",
|
||||
"CheckID": "serfHealth",
|
||||
"Name": "Serf Health Status",
|
||||
"Status": "passing",
|
||||
"Notes": "",
|
||||
"Output": "Agent alive and reachable",
|
||||
"ServiceID": "",
|
||||
"ServiceName": "",
|
||||
"ServiceTags": [],
|
||||
"Type": "",
|
||||
"Interval": "",
|
||||
"Timeout": "",
|
||||
"ExposedPort": 0,
|
||||
"Definition": {},
|
||||
"CreateIndex": 14,
|
||||
"ModifyIndex": 14
|
||||
},
|
||||
{
|
||||
"Node": "node",
|
||||
"CheckID": "service:backend-v2-sidecar-proxy:1",
|
||||
"Name": "Connect Sidecar Listening",
|
||||
"Status": "critical",
|
||||
"Notes": "",
|
||||
"Output": "dial tcp 127.0.0.1:21001: connect: connection refused",
|
||||
"ServiceID": "backend-v2-sidecar-proxy",
|
||||
"ServiceName": "backend-sidecar-proxy",
|
||||
"ServiceTags": [],
|
||||
"Type": "tcp",
|
||||
"Interval": "",
|
||||
"Timeout": "",
|
||||
"ExposedPort": 0,
|
||||
"Definition": {},
|
||||
"CreateIndex": 21,
|
||||
"ModifyIndex": 44
|
||||
},
|
||||
{
|
||||
"Node": "node",
|
||||
"CheckID": "service:backend-v2-sidecar-proxy:2",
|
||||
"Name": "Connect Sidecar Aliasing backend-v2",
|
||||
"Status": "passing",
|
||||
"Notes": "",
|
||||
"Output": "No checks found.",
|
||||
"ServiceID": "backend-v2-sidecar-proxy",
|
||||
"ServiceName": "backend-sidecar-proxy",
|
||||
"ServiceTags": [],
|
||||
"Type": "alias",
|
||||
"Interval": "",
|
||||
"Timeout": "",
|
||||
"ExposedPort": 0,
|
||||
"Definition": {},
|
||||
"CreateIndex": 21,
|
||||
"ModifyIndex": 21
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
|
@ -0,0 +1,32 @@
|
|||
import { moduleFor, test } from 'ember-qunit';
|
||||
moduleFor('service:routlet', 'Integration | Routlet', {
|
||||
// Specify the other units that are required for this test.
|
||||
integration: true,
|
||||
});
|
||||
test('outletFor works', function(assert) {
|
||||
const routlet = this.subject();
|
||||
routlet.addOutlet('application', {
|
||||
name: 'application'
|
||||
});
|
||||
routlet.addRoute('dc', {});
|
||||
routlet.addOutlet('dc', {
|
||||
name: 'dc'
|
||||
});
|
||||
routlet.addRoute('dc.services', {});
|
||||
routlet.addOutlet('dc.services', {
|
||||
name: 'dc.services'
|
||||
});
|
||||
routlet.addRoute('dc.services.instances', {});
|
||||
|
||||
let actual = routlet.outletFor('dc.services');
|
||||
let expected = 'dc';
|
||||
assert.equal(actual.name, expected);
|
||||
|
||||
actual = routlet.outletFor('dc');
|
||||
expected = 'application';
|
||||
assert.equal(actual.name, expected);
|
||||
|
||||
actual = routlet.outletFor('application');
|
||||
expected = undefined;
|
||||
assert.equal(actual, expected);
|
||||
});
|
Loading…
Reference in New Issue