Enable parsing of terminating gateways

This commit is contained in:
Holt Wilkins
2021-06-22 22:47:00 +00:00
parent b5c3f4e9df
commit 898c6c59a6
5 changed files with 183 additions and 13 deletions

View File

@@ -636,9 +636,9 @@ func (e *ConsulIngressConfigEntry) Copy() *ConsulIngressConfigEntry {
type ConsulLinkedService struct {
Name string `hcl:"name,optional"`
CAFile string `hcl:"ca_file,optional"`
CertFile string `hcl:"cert_file,optional"`
KeyFile string `hcl:"key_file,optional"`
CAFile string `hcl:"ca_file,optional" mapstructure:"ca_file"`
CertFile string `hcl:"cert_file,optional" mapstructure:"cert_file"`
KeyFile string `hcl:"key_file,optional" mapstructure:"key_file"`
SNI string `hcl:"sni,optional"`
}

View File

@@ -225,6 +225,7 @@ func parseGateway(o *ast.ObjectItem) (*api.ConsulGateway, error) {
valid := []string{
"proxy",
"ingress",
"terminating",
}
if err := checkHCLKeys(o.Val, valid); err != nil {
@@ -239,6 +240,7 @@ func parseGateway(o *ast.ObjectItem) (*api.ConsulGateway, error) {
delete(m, "proxy")
delete(m, "ingress")
delete(m, "terminating")
dec, err := mapstructure.NewDecoder(&mapstructure.DecoderConfig{
DecodeHook: mapstructure.StringToTimeDurationHookFunc(),
@@ -273,15 +275,30 @@ func parseGateway(o *ast.ObjectItem) (*api.ConsulGateway, error) {
// extract and parse the ingress block
io := listVal.Filter("ingress")
if len(io.Items) != 1 {
// in the future, may be terminating or mesh block instead
return nil, fmt.Errorf("must have one 'ingress' block")
if len(io.Items) == 1 {
ingress, err := parseIngressConfigEntry(io.Items[0])
if err != nil {
return nil, fmt.Errorf("ingress, %v", err)
}
gateway.Ingress = ingress
}
ingress, err := parseIngressConfigEntry(io.Items[0])
if err != nil {
return nil, fmt.Errorf("ingress, %v", err)
if len(io.Items) > 1 {
return nil, fmt.Errorf("ingress, %s", "multiple ingress stanzas not allowed")
}
to := listVal.Filter("terminating")
if len(to.Items) == 1 {
terminating, err := parseTerminatingConfigEntry(to.Items[0])
if err != nil {
return nil, fmt.Errorf("terminating, %v", err)
}
gateway.Terminating = terminating
}
if len(to.Items) > 1 {
return nil, fmt.Errorf("terminating, %s", "multiple terminating stanzas not allowed")
}
gateway.Ingress = ingress
return &gateway, nil
}
@@ -410,6 +427,39 @@ func parseConsulIngressService(o *ast.ObjectItem) (*api.ConsulIngressService, er
return &service, nil
}
func parseConsulLinkedService(o *ast.ObjectItem) (*api.ConsulLinkedService, error) {
valid := []string{
"name",
"ca_file",
"cert_file",
"key_file",
"sni",
}
if err := checkHCLKeys(o.Val, valid); err != nil {
return nil, multierror.Prefix(err, "service ->")
}
var service api.ConsulLinkedService
var m map[string]interface{}
if err := hcl.DecodeObject(&m, o.Val); err != nil {
return nil, err
}
dec, err := mapstructure.NewDecoder(&mapstructure.DecoderConfig{
Result: &service,
})
if err != nil {
return nil, err
}
if err := dec.Decode(m); err != nil {
return nil, err
}
return &service, nil
}
func parseConsulIngressListener(o *ast.ObjectItem) (*api.ConsulIngressListener, error) {
valid := []string{
"port",
@@ -545,6 +595,41 @@ func parseIngressConfigEntry(o *ast.ObjectItem) (*api.ConsulIngressConfigEntry,
return &ingress, nil
}
func parseTerminatingConfigEntry(o *ast.ObjectItem) (*api.ConsulTerminatingConfigEntry, error) {
valid := []string{
"service",
}
if err := checkHCLKeys(o.Val, valid); err != nil {
return nil, multierror.Prefix(err, "terminating ->")
}
var terminating api.ConsulTerminatingConfigEntry
// Parse service(s)
var listVal *ast.ObjectList
if ot, ok := o.Val.(*ast.ObjectType); ok {
listVal = ot.List
} else {
return nil, fmt.Errorf("terminating: should be an object")
}
lo := listVal.Filter("service")
if len(lo.Items) > 0 {
terminating.Services = make([]*api.ConsulLinkedService, len(lo.Items))
for i := range lo.Items {
service, err := parseConsulLinkedService(lo.Items[i])
if err != nil {
return nil, err
}
terminating.Services[i] = service
}
}
return &terminating, nil
}
func parseSidecarService(o *ast.ObjectItem) (*api.ConsulSidecarService, error) {
valid := []string{
"port",

View File

@@ -1532,6 +1532,45 @@ func TestParse(t *testing.T) {
},
false,
},
{
"tg-service-connect-gateway-terminating.hcl",
&api.Job{
ID: stringToPtr("connect_gateway_terminating"),
Name: stringToPtr("connect_gateway_terminating"),
TaskGroups: []*api.TaskGroup{{
Name: stringToPtr("group"),
Services: []*api.Service{{
Name: "terminating-gateway-service",
Connect: &api.ConsulConnect{
Gateway: &api.ConsulGateway{
Proxy: &api.ConsulGatewayProxy{
ConnectTimeout: timeToPtr(3 * time.Second),
EnvoyGatewayBindTaggedAddresses: true,
EnvoyGatewayBindAddresses: map[string]*api.ConsulGatewayBindAddress{
"listener1": {Name: "listener1", Address: "10.0.0.1", Port: 8888},
"listener2": {Name: "listener2", Address: "10.0.0.2", Port: 8889},
},
EnvoyGatewayNoDefaultBind: true,
Config: map[string]interface{}{"foo": "bar"},
},
Terminating: &api.ConsulTerminatingConfigEntry{
Services: []*api.ConsulLinkedService{{
Name: "service1",
CAFile: "ca.pem",
CertFile: "cert.pem",
KeyFile: "key.pem",
}, {
Name: "service2",
SNI: "myhost",
}},
},
},
},
}},
}},
},
false,
},
{
"tg-scaling-policy-minimal.hcl",
&api.Job{

View File

@@ -0,0 +1,46 @@
job "connect_gateway_terminating" {
group "group" {
service {
name = "terminating-gateway-service"
connect {
gateway {
proxy {
connect_timeout = "3s"
envoy_gateway_bind_tagged_addresses = true
envoy_gateway_bind_addresses "listener1" {
address = "10.0.0.1"
port = 8888
}
envoy_gateway_bind_addresses "listener2" {
address = "10.0.0.2"
port = 8889
}
envoy_gateway_no_default_bind = true
config {
foo = "bar"
}
}
terminating {
service {
name = "service1"
ca_file = "ca.pem"
cert_file = "cert.pem"
key_file = "key.pem"
}
service {
name = "service2"
sni = "myhost"
}
}
}
}
}
}
}

View File

@@ -636,9 +636,9 @@ func (e *ConsulIngressConfigEntry) Copy() *ConsulIngressConfigEntry {
type ConsulLinkedService struct {
Name string `hcl:"name,optional"`
CAFile string `hcl:"ca_file,optional"`
CertFile string `hcl:"cert_file,optional"`
KeyFile string `hcl:"key_file,optional"`
CAFile string `hcl:"ca_file,optional" mapstructure:"ca_file"`
CertFile string `hcl:"cert_file,optional" mapstructure:"cert_file"`
KeyFile string `hcl:"key_file,optional" mapstructure:"key_file"`
SNI string `hcl:"sni,optional"`
}