diff --git a/.changelog/14921.txt b/.changelog/14921.txt
new file mode 100644
index 000000000..a9b37cbdd
--- /dev/null
+++ b/.changelog/14921.txt
@@ -0,0 +1,3 @@
+```release-note:feature
+ui: Remove node meta on service instances when using agentless and consolidate external-source labels on service instances page if they all match.
+```
diff --git a/ui/packages/consul-ui/app/components/consul/instance-checks/index.hbs b/ui/packages/consul-ui/app/components/consul/instance-checks/index.hbs
index 1cd603a9e..f1667610c 100644
--- a/ui/packages/consul-ui/app/components/consul/instance-checks/index.hbs
+++ b/ui/packages/consul-ui/app/components/consul/instance-checks/index.hbs
@@ -46,4 +46,4 @@ as |grouped|}}
{{/let}}
{{/let}}
-{{/let}}
\ No newline at end of file
+{{/let}}
diff --git a/ui/packages/consul-ui/app/components/consul/service-instance/list/index.hbs b/ui/packages/consul-ui/app/components/consul/service-instance/list/index.hbs
index 36284cecb..a4e3694a5 100644
--- a/ui/packages/consul-ui/app/components/consul/service-instance/list/index.hbs
+++ b/ui/packages/consul-ui/app/components/consul/service-instance/list/index.hbs
@@ -45,18 +45,24 @@ as |proxy|}}
@items={{filter-by 'ServiceID' '' checks}}
/>
{{else}}
-
+ {{#unless this.areAllExternalSourcesMatching}}
+
+ {{/unless}}
-
+
+ {{#unless item.Node.Meta.synthetic-node}}
+
+ {{/unless}}
{{/if}}
{{#if proxy}}
@@ -70,7 +76,7 @@ as |proxy|}}
{{/if}}
-{{#if (not @node)}}
+{{#if (and (not @node) (not item.Node.Meta.synthetic-node))}}
-
@@ -78,7 +84,7 @@ as |proxy|}}
-
- {{item.Node.Node}}
+ {{item.Node.Node}}
{{/if}}
@@ -114,4 +120,4 @@ as |proxy|}}
-{{/let}}
\ No newline at end of file
+{{/let}}
diff --git a/ui/packages/consul-ui/app/components/consul/service-instance/list/index.js b/ui/packages/consul-ui/app/components/consul/service-instance/list/index.js
new file mode 100644
index 000000000..301db92f8
--- /dev/null
+++ b/ui/packages/consul-ui/app/components/consul/service-instance/list/index.js
@@ -0,0 +1,12 @@
+import Component from '@glimmer/component';
+
+export default class ServiceInstanceList extends Component {
+ get areAllExternalSourcesMatching() {
+ const firstSource = this.args.items[0]?.Service?.Meta?.['external-source'];
+
+ const matching = this.args.items.every(
+ (instance) => instance.Service?.Meta?.['external-source'] === firstSource
+ );
+ return matching;
+ }
+}
diff --git a/ui/packages/consul-ui/tests/acceptance/dc/services/show.feature b/ui/packages/consul-ui/tests/acceptance/dc/services/show.feature
index 6bcee57f4..496b17742 100644
--- a/ui/packages/consul-ui/tests/acceptance/dc/services/show.feature
+++ b/ui/packages/consul-ui/tests/acceptance/dc/services/show.feature
@@ -105,6 +105,148 @@ Feature: dc / services / show: Show Service
- "2.2.2.2:8000"
- "3.3.3.3:8888"
---
+ Scenario: Given a combination of sources I should see them all on the instances
+ Given 1 datacenter model with the value "dc1"
+ And 3 node models
+ And 1 service model from yaml
+ ---
+ - Checks:
+ - Status: critical
+ Service:
+ Kind: ~
+ ID: passing-service-8080
+ Port: 8080
+ Address: 1.1.1.1
+ Meta:
+ external-source: kubernetes
+ Node:
+ Address: 1.2.2.2
+ Meta:
+ synthetic-node: false
+ - Checks:
+ - Status: passing
+ Service:
+ Kind: ~
+ ID: service-8000
+ Port: 8000
+ Address: 2.2.2.2
+ Meta:
+ external-source: kubernetes
+ Node:
+ Address: 2.3.3.3
+ Meta:
+ synthetic-node: false
+ - Checks:
+ - Status: passing
+ Service:
+ Kind: ~
+ ID: service-8888
+ Port: 8888
+ Address: 3.3.3.3
+ Meta:
+ external-source: vault
+ Node:
+ Address: 3.4.4.4
+ Meta:
+ synthetic-node: false
+ ---
+ When I visit the service page for yaml
+ ---
+ dc: dc1
+ service: service-0
+ ---
+ And I click instances on the tabs
+ Then I see externalSource on the instances vertically like yaml
+ ---
+ - "kubernetes"
+ - "kubernetes"
+ - "vault"
+ ---
+ And I see nodeName on the instances like yaml
+ ---
+ - "node-0"
+ - "node-1"
+ - "node-2"
+ ---
+ And I see nodeChecks on the instances
+ Scenario: Given instances share the same external source, only show it at the top
+ Given 1 datacenter model with the value "dc1"
+ And 3 node models
+ And 1 service model from yaml
+ ---
+ - Checks:
+ - Status: critical
+ Service:
+ Kind: ~
+ ID: passing-service-8080
+ Port: 8080
+ Address: 1.1.1.1
+ Meta:
+ external-source: kubernetes
+ Node:
+ Address: 1.2.2.2
+ Meta:
+ synthetic-node: true
+ - Checks:
+ - Status: passing
+ Service:
+ Kind: ~
+ ID: service-8000
+ Port: 8000
+ Address: 2.2.2.2
+ Meta:
+ external-source: kubernetes
+ Node:
+ Address: 2.3.3.3
+ Meta:
+ synthetic-node: true
+ - Checks:
+ - Status: passing
+ Service:
+ Kind: ~
+ ID: service-8888
+ Port: 8888
+ Address: 3.3.3.3
+ Meta:
+ external-source: kubernetes
+ Node:
+ Address: 3.4.4.4
+ ---
+ When I visit the service page for yaml
+ ---
+ dc: dc1
+ service: service-0
+ ---
+ And I click instances on the tabs
+ Then I see externalSource like "kubernetes"
+ And I don't see externalSource on the instances
+ Scenario: Given one agentless instance, it should not show node health checks or node name
+ Given 1 datacenter model with the value "dc1"
+ And 1 node models
+ And 1 service model from yaml
+ ---
+ - Checks:
+ - Status: critical
+ Service:
+ Kind: ~
+ ID: passing-service-8080
+ Port: 8080
+ Address: 1.1.1.1
+ Meta:
+ external-source: kubernetes
+ Node:
+ Address: 1.2.2.2
+ Meta:
+ synthetic-node: true
+ ---
+ When I visit the service page for yaml
+ ---
+ dc: dc1
+ service: service-0
+ ---
+ And I click instances on the tabs
+ And I don't see nodeChecks on the instances
+ And I don't see nodeName on the instances
Scenario: Given a dashboard template has been set
Given 1 datacenter model with the value "dc1"
And ui_config from yaml
diff --git a/ui/packages/consul-ui/tests/pages/dc/services/show.js b/ui/packages/consul-ui/tests/pages/dc/services/show.js
index 25ba98b93..f5b0d04f1 100644
--- a/ui/packages/consul-ui/tests/pages/dc/services/show.js
+++ b/ui/packages/consul-ui/tests/pages/dc/services/show.js
@@ -32,7 +32,10 @@ export default function (
// TODO: These need to somehow move to subpages
instances: collection('.consul-service-instance-list > ul > li:not(:first-child)', {
address: text('[data-test-address]'),
+ externalSource: attribute('data-test-external-source', '[data-test-external-source]'),
instance: clickable('a'),
+ nodeChecks: text('[data-test-node-health-checks]'),
+ nodeName: text('[data-test-node-name]'),
}),
intentionList: intentions(),
};