Add api mod support for /catalog/gateway-services (#8278)
This commit is contained in:
parent
51f71d43ab
commit
a30c10a18c
|
@ -1329,38 +1329,15 @@ func TestCatalog_GatewayServices_Terminating(t *testing.T) {
|
|||
|
||||
testrpc.WaitForTestAgent(t, a.RPC, "dc1")
|
||||
|
||||
// Register a terminating gateway
|
||||
args := &structs.RegisterRequest{
|
||||
Datacenter: "dc1",
|
||||
Node: "foo",
|
||||
Address: "127.0.0.1",
|
||||
Service: &structs.NodeService{
|
||||
Kind: structs.ServiceKindTerminatingGateway,
|
||||
Service: "terminating",
|
||||
Port: 443,
|
||||
},
|
||||
}
|
||||
|
||||
var out struct{}
|
||||
assert.NoError(t, a.RPC("Catalog.Register", &args, &out))
|
||||
|
||||
// Register two services the gateway will route to
|
||||
args = structs.TestRegisterRequest(t)
|
||||
// Register a service to be covered by the wildcard in the config entry
|
||||
args := structs.TestRegisterRequest(t)
|
||||
args.Service.Service = "redis"
|
||||
args.Check = &structs.HealthCheck{
|
||||
Name: "redis",
|
||||
Status: api.HealthPassing,
|
||||
ServiceID: args.Service.Service,
|
||||
}
|
||||
assert.NoError(t, a.RPC("Catalog.Register", &args, &out))
|
||||
|
||||
args = structs.TestRegisterRequest(t)
|
||||
args.Service.Service = "api"
|
||||
args.Check = &structs.HealthCheck{
|
||||
Name: "api",
|
||||
Status: api.HealthPassing,
|
||||
ServiceID: args.Service.Service,
|
||||
}
|
||||
var out struct{}
|
||||
assert.NoError(t, a.RPC("Catalog.Register", &args, &out))
|
||||
|
||||
// Associate the gateway and api/redis services
|
||||
|
@ -1441,41 +1418,7 @@ func TestCatalog_GatewayServices_Ingress(t *testing.T) {
|
|||
|
||||
testrpc.WaitForTestAgent(t, a.RPC, "dc1")
|
||||
|
||||
// Register an ingress gateway
|
||||
args := &structs.RegisterRequest{
|
||||
Datacenter: "dc1",
|
||||
Node: "foo",
|
||||
Address: "127.0.0.1",
|
||||
Service: &structs.NodeService{
|
||||
Kind: structs.ServiceKindTerminatingGateway,
|
||||
Service: "ingress",
|
||||
Port: 444,
|
||||
},
|
||||
}
|
||||
|
||||
var out struct{}
|
||||
require.NoError(t, a.RPC("Catalog.Register", &args, &out))
|
||||
|
||||
// Register two services the gateway will route to
|
||||
args = structs.TestRegisterRequest(t)
|
||||
args.Service.Service = "redis"
|
||||
args.Check = &structs.HealthCheck{
|
||||
Name: "redis",
|
||||
Status: api.HealthPassing,
|
||||
ServiceID: args.Service.Service,
|
||||
}
|
||||
require.NoError(t, a.RPC("Catalog.Register", &args, &out))
|
||||
|
||||
args = structs.TestRegisterRequest(t)
|
||||
args.Service.Service = "api"
|
||||
args.Check = &structs.HealthCheck{
|
||||
Name: "api",
|
||||
Status: api.HealthPassing,
|
||||
ServiceID: args.Service.Service,
|
||||
}
|
||||
require.NoError(t, a.RPC("Catalog.Register", &args, &out))
|
||||
|
||||
// Associate the gateway and db service
|
||||
// Associate an ingress gateway with api/redis
|
||||
entryArgs := &structs.ConfigEntryRequest{
|
||||
Op: structs.ConfigEntryUpsert,
|
||||
Datacenter: "dc1",
|
||||
|
|
|
@ -81,6 +81,29 @@ type CatalogDeregistration struct {
|
|||
Namespace string `json:",omitempty"`
|
||||
}
|
||||
|
||||
type CompoundServiceName struct {
|
||||
Name string
|
||||
|
||||
// Namespacing is a Consul Enterprise feature.
|
||||
Namespace string `json:",omitempty"`
|
||||
}
|
||||
|
||||
// GatewayService associates a gateway with a linked service.
|
||||
// It also contains service-specific gateway configuration like ingress listener port and protocol.
|
||||
type GatewayService struct {
|
||||
Gateway CompoundServiceName
|
||||
Service CompoundServiceName
|
||||
GatewayKind ServiceKind
|
||||
Port int `json:",omitempty"`
|
||||
Protocol string `json:",omitempty"`
|
||||
Hosts []string `json:",omitempty"`
|
||||
CAFile string `json:",omitempty"`
|
||||
CertFile string `json:",omitempty"`
|
||||
KeyFile string `json:",omitempty"`
|
||||
SNI string `json:",omitempty"`
|
||||
FromWildcard bool `json:",omitempty"`
|
||||
}
|
||||
|
||||
// Catalog can be used to query the Catalog endpoints
|
||||
type Catalog struct {
|
||||
c *Client
|
||||
|
@ -283,6 +306,27 @@ func (c *Catalog) NodeServiceList(node string, q *QueryOptions) (*CatalogNodeSer
|
|||
return out, qm, nil
|
||||
}
|
||||
|
||||
// GatewayServices is used to query the services associated with an ingress gateway or terminating gateway.
|
||||
func (c *Catalog) GatewayServices(gateway string, q *QueryOptions) ([]*GatewayService, *QueryMeta, error) {
|
||||
r := c.c.newRequest("GET", "/v1/catalog/gateway-services/"+gateway)
|
||||
r.setQueryOptions(q)
|
||||
rtt, resp, err := requireOK(c.c.doRequest(r))
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
qm := &QueryMeta{}
|
||||
parseQueryMeta(resp, qm)
|
||||
qm.RequestTime = rtt
|
||||
|
||||
var out []*GatewayService
|
||||
if err := decodeBody(resp, &out); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
return out, qm, nil
|
||||
}
|
||||
|
||||
func ParseServiceAddr(addrPort string) (ServiceAddress, error) {
|
||||
port := 0
|
||||
host, portStr, err := net.SplitHostPort(addrPort)
|
||||
|
|
|
@ -7,6 +7,7 @@ import (
|
|||
|
||||
"github.com/hashicorp/consul/sdk/testutil"
|
||||
"github.com/hashicorp/consul/sdk/testutil/retry"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
|
@ -1088,3 +1089,149 @@ func TestAPI_CatalogEnableTagOverride(t *testing.T) {
|
|||
}
|
||||
})
|
||||
}
|
||||
|
||||
func TestAPI_CatalogGatewayServices_Terminating(t *testing.T) {
|
||||
t.Parallel()
|
||||
c, s := makeClient(t)
|
||||
defer s.Stop()
|
||||
s.WaitForSerfCheck(t)
|
||||
|
||||
catalog := c.Catalog()
|
||||
|
||||
// Register a service to be covered by a wildcard in the config entry
|
||||
svc := &AgentService{
|
||||
ID: "redis",
|
||||
Service: "redis",
|
||||
Port: 6379,
|
||||
}
|
||||
reg := &CatalogRegistration{
|
||||
Datacenter: "dc1",
|
||||
Node: "bar",
|
||||
Address: "192.168.10.11",
|
||||
Service: svc,
|
||||
}
|
||||
retry.Run(t, func(r *retry.R) {
|
||||
if _, err := catalog.Register(reg, nil); err != nil {
|
||||
r.Fatal(err)
|
||||
}
|
||||
})
|
||||
|
||||
entries := c.ConfigEntries()
|
||||
|
||||
// Associate the gateway and api/redis services
|
||||
gwEntry := TerminatingGatewayConfigEntry{
|
||||
Kind: TerminatingGateway,
|
||||
Name: "terminating",
|
||||
Services: []LinkedService{
|
||||
{
|
||||
Name: "api",
|
||||
CAFile: "api/ca.crt",
|
||||
CertFile: "api/client.crt",
|
||||
KeyFile: "api/client.key",
|
||||
SNI: "my-domain",
|
||||
},
|
||||
{
|
||||
Name: "*",
|
||||
CAFile: "ca.crt",
|
||||
CertFile: "client.crt",
|
||||
KeyFile: "client.key",
|
||||
SNI: "my-alt-domain",
|
||||
},
|
||||
},
|
||||
}
|
||||
retry.Run(t, func(r *retry.R) {
|
||||
if success, _, err := entries.Set(&gwEntry, nil); err != nil || !success {
|
||||
r.Fatal(err)
|
||||
}
|
||||
})
|
||||
|
||||
expect := []*GatewayService{
|
||||
{
|
||||
Service: CompoundServiceName{"api", defaultNamespace},
|
||||
Gateway: CompoundServiceName{"terminating", defaultNamespace},
|
||||
GatewayKind: ServiceKindTerminatingGateway,
|
||||
CAFile: "api/ca.crt",
|
||||
CertFile: "api/client.crt",
|
||||
KeyFile: "api/client.key",
|
||||
SNI: "my-domain",
|
||||
},
|
||||
{
|
||||
Service: CompoundServiceName{"redis", defaultNamespace},
|
||||
Gateway: CompoundServiceName{"terminating", defaultNamespace},
|
||||
GatewayKind: ServiceKindTerminatingGateway,
|
||||
CAFile: "ca.crt",
|
||||
CertFile: "client.crt",
|
||||
KeyFile: "client.key",
|
||||
SNI: "my-alt-domain",
|
||||
FromWildcard: true,
|
||||
},
|
||||
}
|
||||
retry.Run(t, func(r *retry.R) {
|
||||
resp, _, err := catalog.GatewayServices("terminating", nil)
|
||||
assert.NoError(r, err)
|
||||
assert.Equal(r, expect, resp)
|
||||
})
|
||||
}
|
||||
|
||||
func TestAPI_CatalogGatewayServices_Ingress(t *testing.T) {
|
||||
t.Parallel()
|
||||
c, s := makeClient(t)
|
||||
defer s.Stop()
|
||||
|
||||
s.WaitForSerfCheck(t)
|
||||
|
||||
entries := c.ConfigEntries()
|
||||
|
||||
// Associate the gateway and api/redis services
|
||||
gwEntry := IngressGatewayConfigEntry{
|
||||
Kind: "ingress-gateway",
|
||||
Name: "ingress",
|
||||
Listeners: []IngressListener{
|
||||
{
|
||||
Port: 8888,
|
||||
Services: []IngressService{
|
||||
{
|
||||
Name: "api",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Port: 9999,
|
||||
Services: []IngressService{
|
||||
{
|
||||
Name: "redis",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
retry.Run(t, func(r *retry.R) {
|
||||
if success, _, err := entries.Set(&gwEntry, nil); err != nil || !success {
|
||||
r.Fatal(err)
|
||||
}
|
||||
})
|
||||
|
||||
catalog := c.Catalog()
|
||||
|
||||
expect := []*GatewayService{
|
||||
{
|
||||
Service: CompoundServiceName{"api", defaultNamespace},
|
||||
Gateway: CompoundServiceName{"ingress", defaultNamespace},
|
||||
GatewayKind: ServiceKindIngressGateway,
|
||||
Protocol: "tcp",
|
||||
Port: 8888,
|
||||
},
|
||||
{
|
||||
Service: CompoundServiceName{"redis", defaultNamespace},
|
||||
Gateway: CompoundServiceName{"ingress", defaultNamespace},
|
||||
GatewayKind: ServiceKindIngressGateway,
|
||||
Protocol: "tcp",
|
||||
Port: 9999,
|
||||
},
|
||||
}
|
||||
retry.Run(t, func(r *retry.R) {
|
||||
resp, _, err := catalog.GatewayServices("ingress", nil)
|
||||
assert.NoError(r, err)
|
||||
assert.Equal(r, expect, resp)
|
||||
})
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue