Fix incorrect protocol check on discovery chains with peer targets. (#15833)

This commit is contained in:
Derek Menteer 2022-12-20 10:15:03 -06:00 committed by GitHub
parent 583ac64c27
commit e25f7313e4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 109 additions and 2 deletions

3
.changelog/15833.txt Normal file
View File

@ -0,0 +1,3 @@
```release-note:bug
connect: Fix issue where service-resolver protocol checks incorrectly errored for failover peer targets.
```

View File

@ -889,9 +889,15 @@ RESOLVE_AGAIN:
targetID := target.ServiceID() targetID := target.ServiceID()
// Only validate protocol if it is not a peered service.
// TODO: Add in remote peer protocol validation when building a chain.
// This likely would require querying the imported services, which
// shouldn't belong in the discovery chain compilation here.
if target.Peer == "" {
if err := c.recordServiceProtocol(targetID); err != nil { if err := c.recordServiceProtocol(targetID); err != nil {
return nil, err return nil, err
} }
}
// Fetch the config entry. // Fetch the config entry.
resolver, ok := c.resolvers[targetID] resolver, ok := c.resolvers[targetID]

View File

@ -40,6 +40,8 @@ func TestCompile(t *testing.T) {
"service and subset redirect": testcase_ServiceAndSubsetRedirect(), "service and subset redirect": testcase_ServiceAndSubsetRedirect(),
"datacenter redirect": testcase_DatacenterRedirect(), "datacenter redirect": testcase_DatacenterRedirect(),
"redirect to cluster peer": testcase_PeerRedirect(), "redirect to cluster peer": testcase_PeerRedirect(),
"redirect to cluster peer http proxy-defaults": testcase_PeerRedirectProxyDefHTTP(),
"redirect to cluster peer http service-defaults": testcase_PeerRedirectSvcDefHTTP(),
"datacenter redirect with mesh gateways": testcase_DatacenterRedirect_WithMeshGateways(), "datacenter redirect with mesh gateways": testcase_DatacenterRedirect_WithMeshGateways(),
"service failover": testcase_ServiceFailover(), "service failover": testcase_ServiceFailover(),
"service failover through redirect": testcase_ServiceFailoverThroughRedirect(), "service failover through redirect": testcase_ServiceFailoverThroughRedirect(),
@ -1132,6 +1134,102 @@ func testcase_PeerRedirect() compileTestCase {
return compileTestCase{entries: entries, expect: expect} return compileTestCase{entries: entries, expect: expect}
} }
func testcase_PeerRedirectProxyDefHTTP() compileTestCase {
entries := newEntries()
entries.AddProxyDefaults(&structs.ProxyConfigEntry{
Kind: structs.ProxyDefaults,
Name: structs.ProxyConfigGlobal,
Config: map[string]interface{}{
"Protocol": "http",
},
})
entries.AddResolvers(
&structs.ServiceResolverConfigEntry{
Kind: "service-resolver",
Name: "main",
Redirect: &structs.ServiceResolverRedirect{
Service: "other",
Peer: "cluster-01",
},
},
)
expect := &structs.CompiledDiscoveryChain{
Protocol: "http",
StartNode: "resolver:other.default.default.external.cluster-01",
Nodes: map[string]*structs.DiscoveryGraphNode{
"resolver:other.default.default.external.cluster-01": {
Type: structs.DiscoveryGraphNodeTypeResolver,
Name: "other.default.default.external.cluster-01",
Resolver: &structs.DiscoveryResolver{
Default: true,
ConnectTimeout: 5 * time.Second,
Target: "other.default.default.external.cluster-01",
},
},
},
Targets: map[string]*structs.DiscoveryTarget{
"other.default.default.external.cluster-01": newTarget(structs.DiscoveryTargetOpts{
Service: "other",
Peer: "cluster-01",
}, func(t *structs.DiscoveryTarget) {
t.SNI = ""
t.Name = ""
t.Datacenter = ""
}),
},
}
return compileTestCase{entries: entries, expect: expect}
}
func testcase_PeerRedirectSvcDefHTTP() compileTestCase {
entries := newEntries()
entries.AddServices(
&structs.ServiceConfigEntry{
Kind: structs.ServiceDefaults,
Name: "main",
Protocol: "http",
},
)
entries.AddResolvers(
&structs.ServiceResolverConfigEntry{
Kind: "service-resolver",
Name: "main",
Redirect: &structs.ServiceResolverRedirect{
Service: "other",
Peer: "cluster-01",
},
},
)
expect := &structs.CompiledDiscoveryChain{
Protocol: "http",
StartNode: "resolver:other.default.default.external.cluster-01",
Nodes: map[string]*structs.DiscoveryGraphNode{
"resolver:other.default.default.external.cluster-01": {
Type: structs.DiscoveryGraphNodeTypeResolver,
Name: "other.default.default.external.cluster-01",
Resolver: &structs.DiscoveryResolver{
Default: true,
ConnectTimeout: 5 * time.Second,
Target: "other.default.default.external.cluster-01",
},
},
},
Targets: map[string]*structs.DiscoveryTarget{
"other.default.default.external.cluster-01": newTarget(structs.DiscoveryTargetOpts{
Service: "other",
Peer: "cluster-01",
}, func(t *structs.DiscoveryTarget) {
t.SNI = ""
t.Name = ""
t.Datacenter = ""
}),
},
}
return compileTestCase{entries: entries, expect: expect}
}
func testcase_DatacenterRedirect_WithMeshGateways() compileTestCase { func testcase_DatacenterRedirect_WithMeshGateways() compileTestCase {
entries := newEntries() entries := newEntries()
entries.AddProxyDefaults(&structs.ProxyConfigEntry{ entries.AddProxyDefaults(&structs.ProxyConfigEntry{