|
|
|
@ -223,6 +223,7 @@ func TestUiServices(t *testing.T) {
|
|
|
|
|
Service: &structs.NodeService{
|
|
|
|
|
Kind: structs.ServiceKindTypical,
|
|
|
|
|
Service: "api",
|
|
|
|
|
ID: "api-1",
|
|
|
|
|
Tags: []string{"tag1", "tag2"},
|
|
|
|
|
},
|
|
|
|
|
Checks: structs.HealthChecks{
|
|
|
|
@ -230,18 +231,20 @@ func TestUiServices(t *testing.T) {
|
|
|
|
|
Node: "foo",
|
|
|
|
|
Name: "api svc check",
|
|
|
|
|
ServiceName: "api",
|
|
|
|
|
ServiceID: "api-1",
|
|
|
|
|
Status: api.HealthWarning,
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
// register web svc on node foo
|
|
|
|
|
// register api-proxy svc on node foo
|
|
|
|
|
{
|
|
|
|
|
Datacenter: "dc1",
|
|
|
|
|
Node: "foo",
|
|
|
|
|
SkipNodeUpdate: true,
|
|
|
|
|
Service: &structs.NodeService{
|
|
|
|
|
Kind: structs.ServiceKindConnectProxy,
|
|
|
|
|
Service: "web",
|
|
|
|
|
Service: "api-proxy",
|
|
|
|
|
ID: "api-proxy-1",
|
|
|
|
|
Tags: []string{},
|
|
|
|
|
Meta: map[string]string{metaExternalSource: "k8s"},
|
|
|
|
|
Port: 1234,
|
|
|
|
@ -252,8 +255,9 @@ func TestUiServices(t *testing.T) {
|
|
|
|
|
Checks: structs.HealthChecks{
|
|
|
|
|
&structs.HealthCheck{
|
|
|
|
|
Node: "foo",
|
|
|
|
|
Name: "web svc check",
|
|
|
|
|
ServiceName: "web",
|
|
|
|
|
Name: "api proxy listening",
|
|
|
|
|
ServiceName: "api-proxy",
|
|
|
|
|
ServiceID: "api-proxy-1",
|
|
|
|
|
Status: api.HealthPassing,
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
@ -264,14 +268,12 @@ func TestUiServices(t *testing.T) {
|
|
|
|
|
Node: "bar",
|
|
|
|
|
Address: "127.0.0.2",
|
|
|
|
|
Service: &structs.NodeService{
|
|
|
|
|
Kind: structs.ServiceKindConnectProxy,
|
|
|
|
|
Kind: structs.ServiceKindTypical,
|
|
|
|
|
Service: "web",
|
|
|
|
|
ID: "web-1",
|
|
|
|
|
Tags: []string{},
|
|
|
|
|
Meta: map[string]string{metaExternalSource: "k8s"},
|
|
|
|
|
Port: 1234,
|
|
|
|
|
Proxy: structs.ConnectProxyConfig{
|
|
|
|
|
DestinationServiceName: "api",
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
Checks: []*structs.HealthCheck{
|
|
|
|
|
{
|
|
|
|
@ -279,6 +281,7 @@ func TestUiServices(t *testing.T) {
|
|
|
|
|
Name: "web svc check",
|
|
|
|
|
Status: api.HealthCritical,
|
|
|
|
|
ServiceName: "web",
|
|
|
|
|
ServiceID: "web-1",
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
@ -366,76 +369,107 @@ func TestUiServices(t *testing.T) {
|
|
|
|
|
assertIndex(t, resp)
|
|
|
|
|
|
|
|
|
|
// Should be 2 nodes, and all the empty lists should be non-nil
|
|
|
|
|
summary := obj.([]*ServiceSummary)
|
|
|
|
|
require.Len(t, summary, 5)
|
|
|
|
|
summary := obj.([]*ServiceListingSummary)
|
|
|
|
|
require.Len(t, summary, 6)
|
|
|
|
|
|
|
|
|
|
// internal accounting that users don't see can be blown away
|
|
|
|
|
for _, sum := range summary {
|
|
|
|
|
sum.externalSourceSet = nil
|
|
|
|
|
sum.checks = nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
expected := []*ServiceSummary{
|
|
|
|
|
expected := []*ServiceListingSummary{
|
|
|
|
|
{
|
|
|
|
|
Kind: structs.ServiceKindTypical,
|
|
|
|
|
Name: "api",
|
|
|
|
|
Tags: []string{"tag1", "tag2"},
|
|
|
|
|
Nodes: []string{"foo"},
|
|
|
|
|
InstanceCount: 1,
|
|
|
|
|
ChecksPassing: 2,
|
|
|
|
|
ChecksWarning: 1,
|
|
|
|
|
ChecksCritical: 0,
|
|
|
|
|
ServiceSummary: ServiceSummary{
|
|
|
|
|
Kind: structs.ServiceKindTypical,
|
|
|
|
|
Name: "api",
|
|
|
|
|
Datacenter: "dc1",
|
|
|
|
|
Tags: []string{"tag1", "tag2"},
|
|
|
|
|
Nodes: []string{"foo"},
|
|
|
|
|
InstanceCount: 1,
|
|
|
|
|
ChecksPassing: 2,
|
|
|
|
|
ChecksWarning: 1,
|
|
|
|
|
ChecksCritical: 0,
|
|
|
|
|
EnterpriseMeta: *structs.DefaultEnterpriseMeta(),
|
|
|
|
|
},
|
|
|
|
|
ConnectedWithProxy: true,
|
|
|
|
|
ConnectedWithGateway: true,
|
|
|
|
|
EnterpriseMeta: *structs.DefaultEnterpriseMeta(),
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
Kind: structs.ServiceKindTypical,
|
|
|
|
|
Name: "cache",
|
|
|
|
|
Tags: nil,
|
|
|
|
|
Nodes: []string{"zip"},
|
|
|
|
|
InstanceCount: 1,
|
|
|
|
|
ChecksPassing: 0,
|
|
|
|
|
ChecksWarning: 0,
|
|
|
|
|
ChecksCritical: 0,
|
|
|
|
|
ServiceSummary: ServiceSummary{
|
|
|
|
|
Kind: structs.ServiceKindConnectProxy,
|
|
|
|
|
Name: "api-proxy",
|
|
|
|
|
Datacenter: "dc1",
|
|
|
|
|
Tags: nil,
|
|
|
|
|
Nodes: []string{"foo"},
|
|
|
|
|
InstanceCount: 1,
|
|
|
|
|
ChecksPassing: 2,
|
|
|
|
|
ChecksWarning: 0,
|
|
|
|
|
ChecksCritical: 0,
|
|
|
|
|
ExternalSources: []string{"k8s"},
|
|
|
|
|
EnterpriseMeta: *structs.DefaultEnterpriseMeta(),
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
ServiceSummary: ServiceSummary{
|
|
|
|
|
Kind: structs.ServiceKindTypical,
|
|
|
|
|
Name: "cache",
|
|
|
|
|
Datacenter: "dc1",
|
|
|
|
|
Tags: nil,
|
|
|
|
|
Nodes: []string{"zip"},
|
|
|
|
|
InstanceCount: 1,
|
|
|
|
|
ChecksPassing: 0,
|
|
|
|
|
ChecksWarning: 0,
|
|
|
|
|
ChecksCritical: 0,
|
|
|
|
|
EnterpriseMeta: *structs.DefaultEnterpriseMeta(),
|
|
|
|
|
},
|
|
|
|
|
ConnectedWithGateway: true,
|
|
|
|
|
EnterpriseMeta: *structs.DefaultEnterpriseMeta(),
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
Kind: structs.ServiceKindConnectProxy,
|
|
|
|
|
Name: "web",
|
|
|
|
|
Tags: nil,
|
|
|
|
|
Nodes: []string{"bar", "foo"},
|
|
|
|
|
InstanceCount: 2,
|
|
|
|
|
ChecksPassing: 2,
|
|
|
|
|
ChecksWarning: 1,
|
|
|
|
|
ChecksCritical: 1,
|
|
|
|
|
ExternalSources: []string{"k8s"},
|
|
|
|
|
EnterpriseMeta: *structs.DefaultEnterpriseMeta(),
|
|
|
|
|
ServiceSummary: ServiceSummary{
|
|
|
|
|
Kind: structs.ServiceKindTypical,
|
|
|
|
|
Name: "consul",
|
|
|
|
|
Datacenter: "dc1",
|
|
|
|
|
Tags: nil,
|
|
|
|
|
Nodes: []string{a.Config.NodeName},
|
|
|
|
|
InstanceCount: 1,
|
|
|
|
|
ChecksPassing: 1,
|
|
|
|
|
ChecksWarning: 0,
|
|
|
|
|
ChecksCritical: 0,
|
|
|
|
|
EnterpriseMeta: *structs.DefaultEnterpriseMeta(),
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
Kind: structs.ServiceKindTypical,
|
|
|
|
|
Name: "consul",
|
|
|
|
|
Tags: nil,
|
|
|
|
|
Nodes: []string{a.Config.NodeName},
|
|
|
|
|
InstanceCount: 1,
|
|
|
|
|
ChecksPassing: 1,
|
|
|
|
|
ChecksWarning: 0,
|
|
|
|
|
ChecksCritical: 0,
|
|
|
|
|
EnterpriseMeta: *structs.DefaultEnterpriseMeta(),
|
|
|
|
|
ServiceSummary: ServiceSummary{
|
|
|
|
|
Kind: structs.ServiceKindTerminatingGateway,
|
|
|
|
|
Name: "terminating-gateway",
|
|
|
|
|
Datacenter: "dc1",
|
|
|
|
|
Tags: nil,
|
|
|
|
|
Nodes: []string{"foo"},
|
|
|
|
|
InstanceCount: 1,
|
|
|
|
|
ChecksPassing: 1,
|
|
|
|
|
ChecksWarning: 0,
|
|
|
|
|
ChecksCritical: 0,
|
|
|
|
|
GatewayConfig: GatewayConfig{AssociatedServiceCount: 2},
|
|
|
|
|
EnterpriseMeta: *structs.DefaultEnterpriseMeta(),
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
Kind: structs.ServiceKindTerminatingGateway,
|
|
|
|
|
Name: "terminating-gateway",
|
|
|
|
|
Tags: nil,
|
|
|
|
|
Nodes: []string{"foo"},
|
|
|
|
|
InstanceCount: 1,
|
|
|
|
|
ChecksPassing: 2,
|
|
|
|
|
ChecksWarning: 1,
|
|
|
|
|
GatewayConfig: GatewayConfig{AssociatedServiceCount: 2},
|
|
|
|
|
EnterpriseMeta: *structs.DefaultEnterpriseMeta(),
|
|
|
|
|
ServiceSummary: ServiceSummary{
|
|
|
|
|
Kind: structs.ServiceKindTypical,
|
|
|
|
|
Name: "web",
|
|
|
|
|
Datacenter: "dc1",
|
|
|
|
|
Tags: nil,
|
|
|
|
|
Nodes: []string{"bar"},
|
|
|
|
|
InstanceCount: 1,
|
|
|
|
|
ChecksPassing: 0,
|
|
|
|
|
ChecksWarning: 0,
|
|
|
|
|
ChecksCritical: 1,
|
|
|
|
|
ExternalSources: []string{"k8s"},
|
|
|
|
|
EnterpriseMeta: *structs.DefaultEnterpriseMeta(),
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
require.ElementsMatch(t, expected, summary)
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
@ -448,39 +482,46 @@ func TestUiServices(t *testing.T) {
|
|
|
|
|
assertIndex(t, resp)
|
|
|
|
|
|
|
|
|
|
// Should be 2 nodes, and all the empty lists should be non-nil
|
|
|
|
|
summary := obj.([]*ServiceSummary)
|
|
|
|
|
summary := obj.([]*ServiceListingSummary)
|
|
|
|
|
require.Len(t, summary, 2)
|
|
|
|
|
|
|
|
|
|
// internal accounting that users don't see can be blown away
|
|
|
|
|
for _, sum := range summary {
|
|
|
|
|
sum.externalSourceSet = nil
|
|
|
|
|
sum.checks = nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
expected := []*ServiceSummary{
|
|
|
|
|
expected := []*ServiceListingSummary{
|
|
|
|
|
{
|
|
|
|
|
Kind: structs.ServiceKindTypical,
|
|
|
|
|
Name: "api",
|
|
|
|
|
Tags: []string{"tag1", "tag2"},
|
|
|
|
|
Nodes: []string{"foo"},
|
|
|
|
|
InstanceCount: 1,
|
|
|
|
|
ChecksPassing: 2,
|
|
|
|
|
ChecksWarning: 1,
|
|
|
|
|
ChecksCritical: 0,
|
|
|
|
|
ConnectedWithProxy: true,
|
|
|
|
|
ServiceSummary: ServiceSummary{
|
|
|
|
|
Kind: structs.ServiceKindTypical,
|
|
|
|
|
Name: "api",
|
|
|
|
|
Datacenter: "dc1",
|
|
|
|
|
Tags: []string{"tag1", "tag2"},
|
|
|
|
|
Nodes: []string{"foo"},
|
|
|
|
|
InstanceCount: 1,
|
|
|
|
|
ChecksPassing: 1,
|
|
|
|
|
ChecksWarning: 1,
|
|
|
|
|
ChecksCritical: 0,
|
|
|
|
|
EnterpriseMeta: *structs.DefaultEnterpriseMeta(),
|
|
|
|
|
},
|
|
|
|
|
ConnectedWithProxy: false,
|
|
|
|
|
ConnectedWithGateway: false,
|
|
|
|
|
EnterpriseMeta: *structs.DefaultEnterpriseMeta(),
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
Kind: structs.ServiceKindConnectProxy,
|
|
|
|
|
Name: "web",
|
|
|
|
|
Tags: nil,
|
|
|
|
|
Nodes: []string{"bar", "foo"},
|
|
|
|
|
InstanceCount: 2,
|
|
|
|
|
ChecksPassing: 2,
|
|
|
|
|
ChecksWarning: 1,
|
|
|
|
|
ChecksCritical: 1,
|
|
|
|
|
ExternalSources: []string{"k8s"},
|
|
|
|
|
EnterpriseMeta: *structs.DefaultEnterpriseMeta(),
|
|
|
|
|
ServiceSummary: ServiceSummary{
|
|
|
|
|
Kind: structs.ServiceKindTypical,
|
|
|
|
|
Name: "web",
|
|
|
|
|
Datacenter: "dc1",
|
|
|
|
|
Tags: nil,
|
|
|
|
|
Nodes: []string{"bar"},
|
|
|
|
|
InstanceCount: 1,
|
|
|
|
|
ChecksPassing: 0,
|
|
|
|
|
ChecksWarning: 0,
|
|
|
|
|
ChecksCritical: 1,
|
|
|
|
|
ExternalSources: []string{"k8s"},
|
|
|
|
|
EnterpriseMeta: *structs.DefaultEnterpriseMeta(),
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
}
|
|
|
|
|
require.ElementsMatch(t, expected, summary)
|
|
|
|
@ -582,7 +623,14 @@ func TestUIGatewayServiceNodes_Terminating(t *testing.T) {
|
|
|
|
|
assert.Nil(t, err)
|
|
|
|
|
assertIndex(t, resp)
|
|
|
|
|
|
|
|
|
|
dump := obj.([]*ServiceSummary)
|
|
|
|
|
summary := obj.([]*ServiceSummary)
|
|
|
|
|
|
|
|
|
|
// internal accounting that users don't see can be blown away
|
|
|
|
|
for _, sum := range summary {
|
|
|
|
|
sum.externalSourceSet = nil
|
|
|
|
|
sum.checks = nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
expect := []*ServiceSummary{
|
|
|
|
|
{
|
|
|
|
|
Name: "redis",
|
|
|
|
@ -590,6 +638,7 @@ func TestUIGatewayServiceNodes_Terminating(t *testing.T) {
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
Name: "db",
|
|
|
|
|
Datacenter: "dc1",
|
|
|
|
|
Tags: []string{"backup", "primary"},
|
|
|
|
|
Nodes: []string{"bar", "baz"},
|
|
|
|
|
InstanceCount: 2,
|
|
|
|
@ -599,7 +648,7 @@ func TestUIGatewayServiceNodes_Terminating(t *testing.T) {
|
|
|
|
|
EnterpriseMeta: *structs.DefaultEnterpriseMeta(),
|
|
|
|
|
},
|
|
|
|
|
}
|
|
|
|
|
assert.ElementsMatch(t, expect, dump)
|
|
|
|
|
assert.ElementsMatch(t, expect, summary)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func TestUIGatewayServiceNodes_Ingress(t *testing.T) {
|
|
|
|
@ -748,6 +797,7 @@ func TestUIGatewayServiceNodes_Ingress(t *testing.T) {
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
Name: "db",
|
|
|
|
|
Datacenter: "dc1",
|
|
|
|
|
Tags: []string{"backup", "primary"},
|
|
|
|
|
Nodes: []string{"bar", "baz"},
|
|
|
|
|
InstanceCount: 2,
|
|
|
|
@ -767,6 +817,7 @@ func TestUIGatewayServiceNodes_Ingress(t *testing.T) {
|
|
|
|
|
// internal accounting that users don't see can be blown away
|
|
|
|
|
for _, sum := range dump {
|
|
|
|
|
sum.GatewayConfig.addressesSet = nil
|
|
|
|
|
sum.checks = nil
|
|
|
|
|
}
|
|
|
|
|
assert.ElementsMatch(t, expect, dump)
|
|
|
|
|
}
|
|
|
|
@ -878,3 +929,386 @@ func TestUIEndpoint_modifySummaryForGatewayService_UseRequestedDCInsteadOfConfig
|
|
|
|
|
expected := serviceCanonicalDNSName("test", "ingress", "dc2", "consul", nil) + ":42"
|
|
|
|
|
require.Equal(t, expected, sum.GatewayConfig.Addresses[0])
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func TestUIServiceTopology(t *testing.T) {
|
|
|
|
|
t.Parallel()
|
|
|
|
|
|
|
|
|
|
a := NewTestAgent(t, "")
|
|
|
|
|
defer a.Shutdown()
|
|
|
|
|
|
|
|
|
|
// Register terminating gateway and config entry linking it to postgres + redis
|
|
|
|
|
{
|
|
|
|
|
registrations := map[string]*structs.RegisterRequest{
|
|
|
|
|
"Node foo": {
|
|
|
|
|
Datacenter: "dc1",
|
|
|
|
|
Node: "foo",
|
|
|
|
|
Address: "127.0.0.2",
|
|
|
|
|
Checks: structs.HealthChecks{
|
|
|
|
|
&structs.HealthCheck{
|
|
|
|
|
Node: "foo",
|
|
|
|
|
CheckID: "foo:alive",
|
|
|
|
|
Name: "foo-liveness",
|
|
|
|
|
Status: api.HealthPassing,
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
"Service api on foo": {
|
|
|
|
|
Datacenter: "dc1",
|
|
|
|
|
Node: "foo",
|
|
|
|
|
SkipNodeUpdate: true,
|
|
|
|
|
Service: &structs.NodeService{
|
|
|
|
|
Kind: structs.ServiceKindTypical,
|
|
|
|
|
ID: "api",
|
|
|
|
|
Service: "api",
|
|
|
|
|
Port: 9090,
|
|
|
|
|
Address: "198.18.1.2",
|
|
|
|
|
},
|
|
|
|
|
Checks: structs.HealthChecks{
|
|
|
|
|
&structs.HealthCheck{
|
|
|
|
|
Node: "foo",
|
|
|
|
|
CheckID: "foo:api",
|
|
|
|
|
Name: "api-liveness",
|
|
|
|
|
Status: api.HealthPassing,
|
|
|
|
|
ServiceID: "api",
|
|
|
|
|
ServiceName: "api",
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
"Service api-proxy": {
|
|
|
|
|
Datacenter: "dc1",
|
|
|
|
|
Node: "foo",
|
|
|
|
|
SkipNodeUpdate: true,
|
|
|
|
|
Service: &structs.NodeService{
|
|
|
|
|
Kind: structs.ServiceKindConnectProxy,
|
|
|
|
|
ID: "api-proxy",
|
|
|
|
|
Service: "api-proxy",
|
|
|
|
|
Port: 8443,
|
|
|
|
|
Address: "198.18.1.2",
|
|
|
|
|
Proxy: structs.ConnectProxyConfig{
|
|
|
|
|
DestinationServiceName: "api",
|
|
|
|
|
Upstreams: structs.Upstreams{
|
|
|
|
|
{
|
|
|
|
|
DestinationName: "web",
|
|
|
|
|
LocalBindPort: 8080,
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
Checks: structs.HealthChecks{
|
|
|
|
|
&structs.HealthCheck{
|
|
|
|
|
Node: "foo",
|
|
|
|
|
CheckID: "foo:api-proxy",
|
|
|
|
|
Name: "api proxy listening",
|
|
|
|
|
Status: api.HealthPassing,
|
|
|
|
|
ServiceID: "api-proxy",
|
|
|
|
|
ServiceName: "api-proxy",
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
"Node bar": {
|
|
|
|
|
Datacenter: "dc1",
|
|
|
|
|
Node: "bar",
|
|
|
|
|
Address: "127.0.0.3",
|
|
|
|
|
Checks: structs.HealthChecks{
|
|
|
|
|
&structs.HealthCheck{
|
|
|
|
|
Node: "bar",
|
|
|
|
|
CheckID: "bar:alive",
|
|
|
|
|
Name: "bar-liveness",
|
|
|
|
|
Status: api.HealthPassing,
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
"Service web on bar": {
|
|
|
|
|
Datacenter: "dc1",
|
|
|
|
|
Node: "bar",
|
|
|
|
|
SkipNodeUpdate: true,
|
|
|
|
|
Service: &structs.NodeService{
|
|
|
|
|
Kind: structs.ServiceKindTypical,
|
|
|
|
|
ID: "web",
|
|
|
|
|
Service: "web",
|
|
|
|
|
Port: 80,
|
|
|
|
|
Address: "198.18.1.20",
|
|
|
|
|
},
|
|
|
|
|
Checks: structs.HealthChecks{
|
|
|
|
|
&structs.HealthCheck{
|
|
|
|
|
Node: "bar",
|
|
|
|
|
CheckID: "bar:web",
|
|
|
|
|
Name: "web-liveness",
|
|
|
|
|
Status: api.HealthWarning,
|
|
|
|
|
ServiceID: "web",
|
|
|
|
|
ServiceName: "web",
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
"Service web-proxy on bar": {
|
|
|
|
|
Datacenter: "dc1",
|
|
|
|
|
Node: "bar",
|
|
|
|
|
SkipNodeUpdate: true,
|
|
|
|
|
Service: &structs.NodeService{
|
|
|
|
|
Kind: structs.ServiceKindConnectProxy,
|
|
|
|
|
ID: "web-proxy",
|
|
|
|
|
Service: "web-proxy",
|
|
|
|
|
Port: 8443,
|
|
|
|
|
Address: "198.18.1.20",
|
|
|
|
|
Proxy: structs.ConnectProxyConfig{
|
|
|
|
|
DestinationServiceName: "web",
|
|
|
|
|
Upstreams: structs.Upstreams{
|
|
|
|
|
{
|
|
|
|
|
DestinationName: "redis",
|
|
|
|
|
LocalBindPort: 123,
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
Checks: structs.HealthChecks{
|
|
|
|
|
&structs.HealthCheck{
|
|
|
|
|
Node: "bar",
|
|
|
|
|
CheckID: "bar:web-proxy",
|
|
|
|
|
Name: "web proxy listening",
|
|
|
|
|
Status: api.HealthCritical,
|
|
|
|
|
ServiceID: "web-proxy",
|
|
|
|
|
ServiceName: "web-proxy",
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
"Node baz": {
|
|
|
|
|
Datacenter: "dc1",
|
|
|
|
|
Node: "baz",
|
|
|
|
|
Address: "127.0.0.4",
|
|
|
|
|
Checks: structs.HealthChecks{
|
|
|
|
|
&structs.HealthCheck{
|
|
|
|
|
Node: "baz",
|
|
|
|
|
CheckID: "baz:alive",
|
|
|
|
|
Name: "baz-liveness",
|
|
|
|
|
Status: api.HealthPassing,
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
"Service web on baz": {
|
|
|
|
|
Datacenter: "dc1",
|
|
|
|
|
Node: "baz",
|
|
|
|
|
SkipNodeUpdate: true,
|
|
|
|
|
Service: &structs.NodeService{
|
|
|
|
|
Kind: structs.ServiceKindTypical,
|
|
|
|
|
ID: "web",
|
|
|
|
|
Service: "web",
|
|
|
|
|
Port: 80,
|
|
|
|
|
Address: "198.18.1.40",
|
|
|
|
|
},
|
|
|
|
|
Checks: structs.HealthChecks{
|
|
|
|
|
&structs.HealthCheck{
|
|
|
|
|
Node: "baz",
|
|
|
|
|
CheckID: "baz:web",
|
|
|
|
|
Name: "web-liveness",
|
|
|
|
|
Status: api.HealthPassing,
|
|
|
|
|
ServiceID: "web",
|
|
|
|
|
ServiceName: "web",
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
"Service web-proxy on baz": {
|
|
|
|
|
Datacenter: "dc1",
|
|
|
|
|
Node: "baz",
|
|
|
|
|
SkipNodeUpdate: true,
|
|
|
|
|
Service: &structs.NodeService{
|
|
|
|
|
Kind: structs.ServiceKindConnectProxy,
|
|
|
|
|
ID: "web-proxy",
|
|
|
|
|
Service: "web-proxy",
|
|
|
|
|
Port: 8443,
|
|
|
|
|
Address: "198.18.1.40",
|
|
|
|
|
Proxy: structs.ConnectProxyConfig{
|
|
|
|
|
DestinationServiceName: "web",
|
|
|
|
|
Upstreams: structs.Upstreams{
|
|
|
|
|
{
|
|
|
|
|
DestinationName: "redis",
|
|
|
|
|
LocalBindPort: 123,
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
Checks: structs.HealthChecks{
|
|
|
|
|
&structs.HealthCheck{
|
|
|
|
|
Node: "baz",
|
|
|
|
|
CheckID: "baz:web-proxy",
|
|
|
|
|
Name: "web proxy listening",
|
|
|
|
|
Status: api.HealthCritical,
|
|
|
|
|
ServiceID: "web-proxy",
|
|
|
|
|
ServiceName: "web-proxy",
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
"Node zip": {
|
|
|
|
|
Datacenter: "dc1",
|
|
|
|
|
Node: "zip",
|
|
|
|
|
Address: "127.0.0.5",
|
|
|
|
|
Checks: structs.HealthChecks{
|
|
|
|
|
&structs.HealthCheck{
|
|
|
|
|
Node: "zip",
|
|
|
|
|
CheckID: "zip:alive",
|
|
|
|
|
Name: "zip-liveness",
|
|
|
|
|
Status: api.HealthPassing,
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
"Service redis on zip": {
|
|
|
|
|
Datacenter: "dc1",
|
|
|
|
|
Node: "zip",
|
|
|
|
|
SkipNodeUpdate: true,
|
|
|
|
|
Service: &structs.NodeService{
|
|
|
|
|
Kind: structs.ServiceKindTypical,
|
|
|
|
|
ID: "redis",
|
|
|
|
|
Service: "redis",
|
|
|
|
|
Port: 6379,
|
|
|
|
|
Address: "198.18.1.60",
|
|
|
|
|
},
|
|
|
|
|
Checks: structs.HealthChecks{
|
|
|
|
|
&structs.HealthCheck{
|
|
|
|
|
Node: "zip",
|
|
|
|
|
CheckID: "zip:redis",
|
|
|
|
|
Name: "redis-liveness",
|
|
|
|
|
Status: api.HealthPassing,
|
|
|
|
|
ServiceID: "redis",
|
|
|
|
|
ServiceName: "redis",
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
"Service redis-proxy on zip": {
|
|
|
|
|
Datacenter: "dc1",
|
|
|
|
|
Node: "zip",
|
|
|
|
|
SkipNodeUpdate: true,
|
|
|
|
|
Service: &structs.NodeService{
|
|
|
|
|
Kind: structs.ServiceKindConnectProxy,
|
|
|
|
|
ID: "redis-proxy",
|
|
|
|
|
Service: "redis-proxy",
|
|
|
|
|
Port: 8443,
|
|
|
|
|
Address: "198.18.1.60",
|
|
|
|
|
Proxy: structs.ConnectProxyConfig{
|
|
|
|
|
DestinationServiceName: "redis",
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
Checks: structs.HealthChecks{
|
|
|
|
|
&structs.HealthCheck{
|
|
|
|
|
Node: "zip",
|
|
|
|
|
CheckID: "zip:redis-proxy",
|
|
|
|
|
Name: "redis proxy listening",
|
|
|
|
|
Status: api.HealthCritical,
|
|
|
|
|
ServiceID: "redis-proxy",
|
|
|
|
|
ServiceName: "redis-proxy",
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
}
|
|
|
|
|
for _, args := range registrations {
|
|
|
|
|
var out struct{}
|
|
|
|
|
require.NoError(t, a.RPC("Catalog.Register", args, &out))
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
t.Run("api", func(t *testing.T) {
|
|
|
|
|
// Request topology for api
|
|
|
|
|
req, _ := http.NewRequest("GET", "/v1/internal/ui/service-topology/api", nil)
|
|
|
|
|
resp := httptest.NewRecorder()
|
|
|
|
|
obj, err := a.srv.UIServiceTopology(resp, req)
|
|
|
|
|
assert.Nil(t, err)
|
|
|
|
|
assertIndex(t, resp)
|
|
|
|
|
|
|
|
|
|
expect := ServiceTopology{
|
|
|
|
|
Upstreams: []*ServiceSummary{
|
|
|
|
|
{
|
|
|
|
|
Name: "web",
|
|
|
|
|
Datacenter: "dc1",
|
|
|
|
|
Nodes: []string{"bar", "baz"},
|
|
|
|
|
InstanceCount: 2,
|
|
|
|
|
ChecksPassing: 3,
|
|
|
|
|
ChecksWarning: 1,
|
|
|
|
|
ChecksCritical: 2,
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
FilteredByACLs: false,
|
|
|
|
|
}
|
|
|
|
|
result := obj.(ServiceTopology)
|
|
|
|
|
|
|
|
|
|
// Internal accounting that is not returned in JSON response
|
|
|
|
|
for _, u := range result.Upstreams {
|
|
|
|
|
u.externalSourceSet = nil
|
|
|
|
|
u.checks = nil
|
|
|
|
|
}
|
|
|
|
|
require.Equal(t, expect, result)
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
t.Run("web", func(t *testing.T) {
|
|
|
|
|
// Request topology for web
|
|
|
|
|
req, _ := http.NewRequest("GET", "/v1/internal/ui/service-topology/web", nil)
|
|
|
|
|
resp := httptest.NewRecorder()
|
|
|
|
|
obj, err := a.srv.UIServiceTopology(resp, req)
|
|
|
|
|
assert.Nil(t, err)
|
|
|
|
|
assertIndex(t, resp)
|
|
|
|
|
|
|
|
|
|
expect := ServiceTopology{
|
|
|
|
|
Upstreams: []*ServiceSummary{
|
|
|
|
|
{
|
|
|
|
|
Name: "redis",
|
|
|
|
|
Datacenter: "dc1",
|
|
|
|
|
Nodes: []string{"zip"},
|
|
|
|
|
InstanceCount: 1,
|
|
|
|
|
ChecksPassing: 2,
|
|
|
|
|
ChecksCritical: 1,
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
Downstreams: []*ServiceSummary{
|
|
|
|
|
{
|
|
|
|
|
Name: "api",
|
|
|
|
|
Datacenter: "dc1",
|
|
|
|
|
Nodes: []string{"foo"},
|
|
|
|
|
InstanceCount: 1,
|
|
|
|
|
ChecksPassing: 3,
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
FilteredByACLs: false,
|
|
|
|
|
}
|
|
|
|
|
result := obj.(ServiceTopology)
|
|
|
|
|
|
|
|
|
|
// Internal accounting that is not returned in JSON response
|
|
|
|
|
for _, u := range result.Upstreams {
|
|
|
|
|
u.externalSourceSet = nil
|
|
|
|
|
u.checks = nil
|
|
|
|
|
}
|
|
|
|
|
for _, d := range result.Downstreams {
|
|
|
|
|
d.externalSourceSet = nil
|
|
|
|
|
d.checks = nil
|
|
|
|
|
}
|
|
|
|
|
require.Equal(t, expect, result)
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
t.Run("redis", func(t *testing.T) {
|
|
|
|
|
// Request topology for redis
|
|
|
|
|
req, _ := http.NewRequest("GET", "/v1/internal/ui/service-topology/redis", nil)
|
|
|
|
|
resp := httptest.NewRecorder()
|
|
|
|
|
obj, err := a.srv.UIServiceTopology(resp, req)
|
|
|
|
|
assert.Nil(t, err)
|
|
|
|
|
assertIndex(t, resp)
|
|
|
|
|
|
|
|
|
|
expect := ServiceTopology{
|
|
|
|
|
Downstreams: []*ServiceSummary{
|
|
|
|
|
{
|
|
|
|
|
Name: "web",
|
|
|
|
|
Datacenter: "dc1",
|
|
|
|
|
Nodes: []string{"bar", "baz"},
|
|
|
|
|
InstanceCount: 2,
|
|
|
|
|
ChecksPassing: 3,
|
|
|
|
|
ChecksWarning: 1,
|
|
|
|
|
ChecksCritical: 2,
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
FilteredByACLs: false,
|
|
|
|
|
}
|
|
|
|
|
result := obj.(ServiceTopology)
|
|
|
|
|
|
|
|
|
|
// Internal accounting that is not returned in JSON response
|
|
|
|
|
for _, d := range result.Downstreams {
|
|
|
|
|
d.externalSourceSet = nil
|
|
|
|
|
d.checks = nil
|
|
|
|
|
}
|
|
|
|
|
require.Equal(t, expect, result)
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|