Create HTTP endpoint
This commit is contained in:
parent
806b1fb608
commit
1cab73e609
|
@ -414,3 +414,43 @@ RETRY_ONCE:
|
|||
[]metrics.Label{{Name: "node", Value: s.nodeName()}})
|
||||
return &out.NodeServices, nil
|
||||
}
|
||||
|
||||
func (s *HTTPServer) CatalogGatewayServices(resp http.ResponseWriter, req *http.Request) (interface{}, error) {
|
||||
metrics.IncrCounterWithLabels([]string{"client", "api", "catalog_gateway_services"}, 1,
|
||||
[]metrics.Label{{Name: "node", Value: s.nodeName()}})
|
||||
|
||||
var args structs.ServiceSpecificRequest
|
||||
|
||||
if err := s.parseEntMetaNoWildcard(req, &args.EnterpriseMeta); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if done := s.parse(resp, req, &args.Datacenter, &args.QueryOptions); done {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// Pull out the gateway's service name
|
||||
args.ServiceName = strings.TrimPrefix(req.URL.Path, "/v1/catalog/gateway-services/")
|
||||
if args.ServiceName == "" {
|
||||
resp.WriteHeader(http.StatusBadRequest)
|
||||
fmt.Fprint(resp, "Missing gateway name")
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// Make the RPC request
|
||||
var out structs.IndexedGatewayServices
|
||||
defer setMeta(resp, &out.QueryMeta)
|
||||
RETRY_ONCE:
|
||||
if err := s.agent.RPC("Catalog.GatewayServices", &args, &out); err != nil {
|
||||
metrics.IncrCounterWithLabels([]string{"client", "rpc", "error", "catalog_gateway_services"}, 1,
|
||||
[]metrics.Label{{Name: "node", Value: s.nodeName()}})
|
||||
return nil, err
|
||||
}
|
||||
if args.QueryOptions.AllowStale && args.MaxStaleDuration > 0 && args.MaxStaleDuration < out.LastContact {
|
||||
args.AllowStale = false
|
||||
args.MaxStaleDuration = 0
|
||||
goto RETRY_ONCE
|
||||
}
|
||||
out.ConsistencyLevel = args.QueryOptions.ConsistencyLevel()
|
||||
|
||||
return out.Services, nil
|
||||
}
|
||||
|
|
|
@ -2,6 +2,7 @@ package agent
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/hashicorp/consul/api"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"net/url"
|
||||
|
@ -1320,3 +1321,225 @@ func TestCatalogNodeServices_WanTranslation(t *testing.T) {
|
|||
require.Equal(t, ns2.Address, "127.0.0.1")
|
||||
require.Equal(t, ns2.Port, 8080)
|
||||
}
|
||||
|
||||
func TestCatalog_GatewayServices_Terminating(t *testing.T) {
|
||||
t.Parallel()
|
||||
a := NewTestAgent(t, "")
|
||||
defer a.Shutdown()
|
||||
|
||||
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)
|
||||
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,
|
||||
}
|
||||
assert.NoError(t, a.RPC("Catalog.Register", &args, &out))
|
||||
|
||||
// Associate the gateway and api/redis services
|
||||
entryArgs := &structs.ConfigEntryRequest{
|
||||
Op: structs.ConfigEntryUpsert,
|
||||
Datacenter: "dc1",
|
||||
Entry: &structs.TerminatingGatewayConfigEntry{
|
||||
Kind: "terminating-gateway",
|
||||
Name: "terminating",
|
||||
Services: []structs.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",
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
var entryResp bool
|
||||
assert.NoError(t, a.RPC("ConfigEntry.Apply", &entryArgs, &entryResp))
|
||||
|
||||
retry.Run(t, func(r *retry.R) {
|
||||
req, _ := http.NewRequest("GET", "/v1/catalog/gateway-services/terminating", nil)
|
||||
resp := httptest.NewRecorder()
|
||||
obj, err := a.srv.CatalogGatewayServices(resp, req)
|
||||
assert.NoError(r, err)
|
||||
|
||||
header := resp.Header().Get("X-Consul-Index")
|
||||
if header == "" || header == "0" {
|
||||
r.Fatalf("Bad: %v", header)
|
||||
}
|
||||
|
||||
gatewayServices := obj.(structs.GatewayServices)
|
||||
|
||||
expect := structs.GatewayServices{
|
||||
{
|
||||
Service: structs.NewServiceID("api", nil),
|
||||
Gateway: structs.NewServiceID("terminating", nil),
|
||||
GatewayKind: structs.ServiceKindTerminatingGateway,
|
||||
CAFile: "api/ca.crt",
|
||||
CertFile: "api/client.crt",
|
||||
KeyFile: "api/client.key",
|
||||
SNI: "my-domain",
|
||||
},
|
||||
{
|
||||
Service: structs.NewServiceID("redis", nil),
|
||||
Gateway: structs.NewServiceID("terminating", nil),
|
||||
GatewayKind: structs.ServiceKindTerminatingGateway,
|
||||
CAFile: "ca.crt",
|
||||
CertFile: "client.crt",
|
||||
KeyFile: "client.key",
|
||||
SNI: "my-alt-domain",
|
||||
FromWildcard: true,
|
||||
},
|
||||
}
|
||||
|
||||
// Ignore raft index for equality
|
||||
for _, s := range gatewayServices {
|
||||
s.RaftIndex = structs.RaftIndex{}
|
||||
}
|
||||
assert.Equal(r, expect, gatewayServices)
|
||||
})
|
||||
}
|
||||
|
||||
func TestCatalog_GatewayServices_Ingress(t *testing.T) {
|
||||
t.Parallel()
|
||||
a := NewTestAgent(t, "")
|
||||
defer a.Shutdown()
|
||||
|
||||
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
|
||||
entryArgs := &structs.ConfigEntryRequest{
|
||||
Op: structs.ConfigEntryUpsert,
|
||||
Datacenter: "dc1",
|
||||
Entry: &structs.IngressGatewayConfigEntry{
|
||||
Kind: "ingress-gateway",
|
||||
Name: "ingress",
|
||||
Listeners: []structs.IngressListener{
|
||||
{
|
||||
Port: 8888,
|
||||
Services: []structs.IngressService{
|
||||
{
|
||||
Name: "api",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Port: 9999,
|
||||
Services: []structs.IngressService{
|
||||
{
|
||||
Name: "redis",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
var entryResp bool
|
||||
require.NoError(t, a.RPC("ConfigEntry.Apply", &entryArgs, &entryResp))
|
||||
|
||||
retry.Run(t, func(r *retry.R) {
|
||||
req, _ := http.NewRequest("GET", "/v1/catalog/gateway-services/ingress", nil)
|
||||
resp := httptest.NewRecorder()
|
||||
obj, err := a.srv.CatalogGatewayServices(resp, req)
|
||||
require.NoError(r, err)
|
||||
|
||||
header := resp.Header().Get("X-Consul-Index")
|
||||
if header == "" || header == "0" {
|
||||
r.Fatalf("Bad: %v", header)
|
||||
}
|
||||
|
||||
gatewayServices := obj.(structs.GatewayServices)
|
||||
|
||||
expect := structs.GatewayServices{
|
||||
{
|
||||
Service: structs.NewServiceID("api", nil),
|
||||
Gateway: structs.NewServiceID("ingress", nil),
|
||||
GatewayKind: structs.ServiceKindIngressGateway,
|
||||
Protocol: "tcp",
|
||||
Port: 8888,
|
||||
},
|
||||
{
|
||||
Service: structs.NewServiceID("redis", nil),
|
||||
Gateway: structs.NewServiceID("ingress", nil),
|
||||
GatewayKind: structs.ServiceKindIngressGateway,
|
||||
Protocol: "tcp",
|
||||
Port: 9999,
|
||||
},
|
||||
}
|
||||
|
||||
// Ignore raft index for equality
|
||||
for _, s := range gatewayServices {
|
||||
s.RaftIndex = structs.RaftIndex{}
|
||||
}
|
||||
require.Equal(r, expect, gatewayServices)
|
||||
})
|
||||
}
|
||||
|
|
|
@ -68,6 +68,7 @@ func init() {
|
|||
registerEndpoint("/v1/catalog/service/", []string{"GET"}, (*HTTPServer).CatalogServiceNodes)
|
||||
registerEndpoint("/v1/catalog/node/", []string{"GET"}, (*HTTPServer).CatalogNodeServices)
|
||||
registerEndpoint("/v1/catalog/node-services/", []string{"GET"}, (*HTTPServer).CatalogNodeServiceList)
|
||||
registerEndpoint("/v1/catalog/gateway-services/", []string{"GET"}, (*HTTPServer).CatalogGatewayServices)
|
||||
registerEndpoint("/v1/config/", []string{"GET", "DELETE"}, (*HTTPServer).Config)
|
||||
registerEndpoint("/v1/config", []string{"PUT"}, (*HTTPServer).ConfigApply)
|
||||
registerEndpoint("/v1/connect/ca/configuration", []string{"GET", "PUT"}, (*HTTPServer).ConnectCAConfiguration)
|
||||
|
|
Loading…
Reference in a new issue