update gateway-services table with endpoints (#13217)

* update gateway-services table with endpoints

* fix failing test

* remove unneeded config in test

* rename "endpoint" to "destination"

* more endpoint renaming to destination in tests

* update isDestination based on service-defaults config entry creation

* use a 3 state kind to be able to set the kind to unknown (when neither a service or a destination exist)

* set unknown state to empty to avoid modifying alot of tests

* fix logic to set the kind correctly on CRUD

* fix failing tests

* add missing tests and fix service delete

* fix failing test

* Apply suggestions from code review

Co-authored-by: Dan Stough <dan.stough@hashicorp.com>

* fix a bug with kind and add relevant test

* fix compile error

* fix failing tests

* add kind to clone

* fix failing tests

* fix failing tests in catalog endpoint

* fix service dump test

* Apply suggestions from code review

Co-authored-by: Dan Stough <dan.stough@hashicorp.com>

* remove duplicate tests

* rename consts and fix kind when no destination is defined in the service-defaults.

* rename Kind to ServiceKind and change switch to use .(type)

Co-authored-by: Dan Stough <dan.stough@hashicorp.com>
This commit is contained in:
Dhia Ayachi 2022-05-31 16:20:12 -04:00 committed by GitHub
parent f0a9b30174
commit 1b779240ae
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 858 additions and 71 deletions

View File

@ -3054,6 +3054,7 @@ func TestCatalog_GatewayServices_TerminatingGateway(t *testing.T) {
CertFile: "api/client.crt",
KeyFile: "api/client.key",
SNI: "my-domain",
ServiceKind: structs.GatewayServiceKindService,
},
{
Service: structs.NewServiceName("db", nil),
@ -3062,6 +3063,7 @@ func TestCatalog_GatewayServices_TerminatingGateway(t *testing.T) {
CAFile: "",
CertFile: "",
KeyFile: "",
ServiceKind: structs.GatewayServiceKindService,
},
{
Service: structs.NewServiceName("redis", nil),
@ -3206,6 +3208,7 @@ func TestCatalog_GatewayServices_BothGateways(t *testing.T) {
Service: structs.NewServiceName("api", nil),
Gateway: structs.NewServiceName("gateway", nil),
GatewayKind: structs.ServiceKindTerminatingGateway,
ServiceKind: structs.GatewayServiceKindService,
},
}
@ -3428,11 +3431,13 @@ service "gateway" {
Service: structs.NewServiceName("db", nil),
Gateway: structs.NewServiceName("gateway", nil),
GatewayKind: structs.ServiceKindTerminatingGateway,
ServiceKind: structs.GatewayServiceKindService,
},
{
Service: structs.NewServiceName("db_replica", nil),
Gateway: structs.NewServiceName("gateway", nil),
GatewayKind: structs.ServiceKindTerminatingGateway,
ServiceKind: structs.GatewayServiceKindUnknown,
},
}

View File

@ -1122,6 +1122,7 @@ func TestInternal_GatewayServiceDump_Terminating(t *testing.T) {
Gateway: structs.NewServiceName("terminating-gateway", nil),
Service: structs.NewServiceName("db", nil),
GatewayKind: "terminating-gateway",
ServiceKind: structs.GatewayServiceKindService,
},
},
{
@ -1155,6 +1156,7 @@ func TestInternal_GatewayServiceDump_Terminating(t *testing.T) {
Gateway: structs.NewServiceName("terminating-gateway", nil),
Service: structs.NewServiceName("db", nil),
GatewayKind: "terminating-gateway",
ServiceKind: structs.GatewayServiceKindService,
},
},
{

View File

@ -846,9 +846,16 @@ func ensureServiceTxn(tx WriteTxn, idx uint64, node string, preserveIndexes bool
}
if svc.PeerName == "" {
// Check if this service is covered by a gateway's wildcard specifier
if err = checkGatewayWildcardsAndUpdate(tx, idx, svc); err != nil {
return fmt.Errorf("failed updating gateway mapping: %s", err)
// Do not associate non-typical services with gateways or consul services
if svc.Kind == structs.ServiceKindTypical && svc.Service != "consul" {
// Check if this service is covered by a gateway's wildcard specifier, we force the service kind to a gateway-service here as that take precedence
sn := structs.NewServiceName(svc.Service, &svc.EnterpriseMeta)
if err = checkGatewayWildcardsAndUpdate(tx, idx, &sn, structs.GatewayServiceKindService); err != nil {
return fmt.Errorf("failed updating gateway mapping: %s", err)
}
if err = checkGatewayAndUpdate(tx, idx, &sn, structs.GatewayServiceKindService); err != nil {
return fmt.Errorf("failed updating gateway mapping: %s", err)
}
}
}
if err := upsertKindServiceName(tx, idx, svc.Kind, svc.CompoundServiceName()); err != nil {
@ -3484,6 +3491,10 @@ func terminatingConfigGatewayServices(
var gatewayServices structs.GatewayServices
for _, svc := range entry.Services {
kind, err := GatewayServiceKind(tx, svc.Name, &svc.EnterpriseMeta)
if err != nil {
return false, nil, fmt.Errorf("failed to get gateway service kind for service %s: %v", svc.Name, err)
}
mapping := &structs.GatewayService{
Gateway: gateway,
Service: structs.NewServiceName(svc.Name, &svc.EnterpriseMeta),
@ -3492,6 +3503,7 @@ func terminatingConfigGatewayServices(
CertFile: svc.CertFile,
CAFile: svc.CAFile,
SNI: svc.SNI,
ServiceKind: kind,
}
gatewayServices = append(gatewayServices, mapping)
@ -3499,6 +3511,34 @@ func terminatingConfigGatewayServices(
return false, gatewayServices, nil
}
func GatewayServiceKind(tx ReadTxn, name string, entMeta *acl.EnterpriseMeta) (structs.GatewayServiceKind, error) {
serviceIter, err := tx.First(tableServices, indexService, Query{
Value: name,
EnterpriseMeta: *entMeta,
})
if err != nil {
return structs.GatewayServiceKindUnknown, err
}
if serviceIter != nil {
return structs.GatewayServiceKindService, err
}
_, entry, err := configEntryTxn(tx, nil, structs.ServiceDefaults, name, entMeta)
if err != nil {
return structs.GatewayServiceKindUnknown, err
}
if entry != nil {
sd, ok := entry.(*structs.ServiceConfigEntry)
if !ok {
return structs.GatewayServiceKindUnknown, fmt.Errorf("invalid config entry type %T", entry)
}
if sd.Destination != nil {
return structs.GatewayServiceKindDestination, nil
}
}
return structs.GatewayServiceKindUnknown, nil
}
// updateGatewayNamespace is used to target all services within a namespace
func updateGatewayNamespace(tx WriteTxn, idx uint64, service *structs.GatewayService, entMeta *acl.EnterpriseMeta) error {
if entMeta == nil {
@ -3539,6 +3579,41 @@ func updateGatewayNamespace(tx WriteTxn, idx uint64, service *structs.GatewaySer
return err
}
}
entries, err := tx.Get(tableConfigEntries, indexID+"_prefix", ConfigEntryKindQuery{Kind: structs.ServiceDefaults, EnterpriseMeta: *entMeta})
if err != nil {
return fmt.Errorf("failed querying entries: %s", err)
}
for entry := entries.Next(); entry != nil; entry = entries.Next() {
e := entry.(*structs.ServiceConfigEntry)
if e.Destination == nil {
continue
}
sn := structs.ServiceName{
Name: e.Name,
EnterpriseMeta: e.EnterpriseMeta,
}
existing, err := tx.First(tableGatewayServices, indexID, service.Gateway, sn, service.Port)
if err != nil {
return fmt.Errorf("gateway service lookup failed: %s", err)
}
if existing != nil {
// If there's an existing service associated with this gateway then we skip it.
// This means the service was specified on its own, and the service entry overrides the wildcard entry.
continue
}
mapping := service.Clone()
mapping.Service = structs.NewServiceName(e.Name, &service.Service.EnterpriseMeta)
mapping.ServiceKind = structs.GatewayServiceKindDestination
mapping.FromWildcard = true
err = updateGatewayService(tx, idx, mapping)
if err != nil {
return err
}
}
// Also store a mapping for the wildcard so that the TLS creds can be pulled
// for new services registered in its namespace
@ -3586,16 +3661,11 @@ func updateGatewayService(tx WriteTxn, idx uint64, mapping *structs.GatewayServi
// checkWildcardForGatewaysAndUpdate checks whether a service matches a
// wildcard definition in gateway config entries and if so adds it the the
// gateway-services table.
func checkGatewayWildcardsAndUpdate(tx WriteTxn, idx uint64, svc *structs.NodeService) error {
// Do not associate non-typical services with gateways or consul services
if svc.Kind != structs.ServiceKindTypical || svc.Service == "consul" {
return nil
}
func checkGatewayWildcardsAndUpdate(tx WriteTxn, idx uint64, svc *structs.ServiceName, kind structs.GatewayServiceKind) error {
sn := structs.ServiceName{Name: structs.WildcardSpecifier, EnterpriseMeta: svc.EnterpriseMeta}
svcGateways, err := tx.Get(tableGatewayServices, indexService, sn)
if err != nil {
return fmt.Errorf("failed gateway lookup for %q: %s", svc.Service, err)
return fmt.Errorf("failed gateway lookup for %q: %s", svc.Name, err)
}
for service := svcGateways.Next(); service != nil; service = svcGateways.Next() {
if wildcardSvc, ok := service.(*structs.GatewayService); ok && wildcardSvc != nil {
@ -3603,8 +3673,9 @@ func checkGatewayWildcardsAndUpdate(tx WriteTxn, idx uint64, svc *structs.NodeSe
// Copy the wildcard mapping and modify it
gatewaySvc := wildcardSvc.Clone()
gatewaySvc.Service = structs.NewServiceName(svc.Service, &svc.EnterpriseMeta)
gatewaySvc.Service = structs.NewServiceName(svc.Name, &svc.EnterpriseMeta)
gatewaySvc.FromWildcard = true
gatewaySvc.ServiceKind = kind
if err = updateGatewayService(tx, idx, gatewaySvc); err != nil {
return fmt.Errorf("Failed to associate service %q with gateway %q", gatewaySvc.Service.String(), gatewaySvc.Gateway.String())
@ -3614,6 +3685,31 @@ func checkGatewayWildcardsAndUpdate(tx WriteTxn, idx uint64, svc *structs.NodeSe
return nil
}
// checkGatewayAndUpdate checks whether a service matches a
// wildcard definition in gateway config entries and if so adds it the the
// gateway-services table.
func checkGatewayAndUpdate(tx WriteTxn, idx uint64, svc *structs.ServiceName, kind structs.GatewayServiceKind) error {
sn := structs.ServiceName{Name: svc.Name, EnterpriseMeta: svc.EnterpriseMeta}
svcGateways, err := tx.First(tableGatewayServices, indexService, sn)
if err != nil {
return fmt.Errorf("failed gateway lookup for %q: %s", svc.Name, err)
}
if service, ok := svcGateways.(*structs.GatewayService); ok && service != nil {
// Copy the wildcard mapping and modify it
gatewaySvc := service.Clone()
gatewaySvc.Service = structs.NewServiceName(svc.Name, &svc.EnterpriseMeta)
gatewaySvc.ServiceKind = kind
if err = updateGatewayService(tx, idx, gatewaySvc); err != nil {
return fmt.Errorf("Failed to associate service %q with gateway %q", gatewaySvc.Service.String(), gatewaySvc.Gateway.String())
}
}
return nil
}
func cleanupGatewayWildcards(tx WriteTxn, idx uint64, svc *structs.ServiceNode) error {
// Clean up association between service name and gateways if needed
sn := structs.ServiceName{Name: svc.ServiceName, EnterpriseMeta: svc.EnterpriseMeta}
@ -3644,6 +3740,12 @@ func cleanupGatewayWildcards(tx WriteTxn, idx uint64, svc *structs.ServiceNode)
if err := deleteGatewayServiceTopologyMapping(tx, idx, m); err != nil {
return fmt.Errorf("failed to reconcile mesh topology for gateway: %v", err)
}
} else {
kind, err := GatewayServiceKind(tx, m.Service.Name, &m.Service.EnterpriseMeta)
if err != nil {
return fmt.Errorf("failed to get gateway service kind for service %s: %v", svc.ServiceName, err)
}
checkGatewayAndUpdate(tx, idx, &structs.ServiceName{Name: m.Service.Name, EnterpriseMeta: m.Service.EnterpriseMeta}, kind)
}
}
return nil

View File

@ -1473,6 +1473,18 @@ func TestServiceHealthEventsFromChanges(t *testing.T) {
},
WantEvents: []stream.Event{
testServiceHealthEvent(t, "srv1", evNodeUnchanged),
testServiceHealthDeregistrationEvent(t,
"tgate1",
evConnectTopic,
evServiceTermingGateway("srv1"),
evTerminatingGatewayVirtualIPs("srv1"),
),
testServiceHealthEvent(t,
"tgate1",
evConnectTopic,
evNodeUnchanged,
evServiceUnchanged,
evServiceTermingGateway("srv1")),
},
})
run(t, eventsTestCase{
@ -1505,6 +1517,18 @@ func TestServiceHealthEventsFromChanges(t *testing.T) {
},
WantEvents: []stream.Event{
testServiceHealthDeregistrationEvent(t, "srv1"),
testServiceHealthDeregistrationEvent(t,
"tgate1",
evConnectTopic,
evServiceTermingGateway("srv1"),
evTerminatingGatewayVirtualIPs("srv1"),
),
testServiceHealthEvent(t,
"tgate1",
evConnectTopic,
evNodeUnchanged,
evServiceUnchanged,
evServiceTermingGateway("srv1")),
},
})
run(t, eventsTestCase{
@ -1625,6 +1649,92 @@ func TestServiceHealthEventsFromChanges(t *testing.T) {
evTerminatingGatewayVirtualIPs("srv1", "srv2")),
},
})
run(t, eventsTestCase{
Name: "terminating gateway destination service-defaults",
Setup: func(s *Store, tx *txn) error {
configEntry := &structs.TerminatingGatewayConfigEntry{
Kind: structs.TerminatingGateway,
Name: "tgate1",
Services: []structs.LinkedService{
{
Name: "destination1",
EnterpriseMeta: *structs.DefaultEnterpriseMetaInDefaultPartition(),
},
},
EnterpriseMeta: *structs.DefaultEnterpriseMetaInDefaultPartition(),
}
err := ensureConfigEntryTxn(tx, tx.Index, configEntry)
if err != nil {
return err
}
return s.ensureRegistrationTxn(tx, tx.Index, false,
testServiceRegistration(t, "tgate1", regTerminatingGateway), false)
},
Mutate: func(s *Store, tx *txn) error {
configEntryDest := &structs.ServiceConfigEntry{
Kind: structs.ServiceDefaults,
Name: "destination1",
Destination: &structs.DestinationConfig{Port: 9000, Address: "kafka.test.com"},
}
return ensureConfigEntryTxn(tx, tx.Index, configEntryDest)
},
WantEvents: []stream.Event{
testServiceHealthDeregistrationEvent(t,
"tgate1",
evConnectTopic,
evServiceTermingGateway("destination1"),
evTerminatingGatewayVirtualIPs("destination1")),
testServiceHealthEvent(t,
"tgate1",
evConnectTopic,
evNodeUnchanged,
evServiceUnchanged,
evServiceTermingGateway("destination1"),
evTerminatingGatewayVirtualIPs("destination1"),
),
},
})
run(t, eventsTestCase{
Name: "terminating gateway destination service-defaults wildcard",
Setup: func(s *Store, tx *txn) error {
configEntry := &structs.TerminatingGatewayConfigEntry{
Kind: structs.TerminatingGateway,
Name: "tgate1",
Services: []structs.LinkedService{
{
Name: "*",
EnterpriseMeta: *structs.DefaultEnterpriseMetaInDefaultPartition(),
},
},
EnterpriseMeta: *structs.DefaultEnterpriseMetaInDefaultPartition(),
}
err := ensureConfigEntryTxn(tx, tx.Index, configEntry)
if err != nil {
return err
}
return s.ensureRegistrationTxn(tx, tx.Index, false,
testServiceRegistration(t, "tgate1", regTerminatingGateway), false)
},
Mutate: func(s *Store, tx *txn) error {
configEntryDest := &structs.ServiceConfigEntry{
Kind: structs.ServiceDefaults,
Name: "destination1",
Destination: &structs.DestinationConfig{Port: 9000, Address: "kafka.test.com"},
}
return ensureConfigEntryTxn(tx, tx.Index, configEntryDest)
},
WantEvents: []stream.Event{
testServiceHealthEvent(t,
"tgate1",
evConnectTopic,
evNodeUnchanged,
evServiceUnchanged,
evServiceTermingGateway("destination1"),
evTerminatingGatewayVirtualIPs("*"),
),
},
})
}
func (tc eventsTestCase) run(t *testing.T) {

View File

@ -5038,6 +5038,7 @@ func TestStateStore_GatewayServices_Terminating(t *testing.T) {
CreateIndex: 21,
ModifyIndex: 21,
},
ServiceKind: structs.GatewayServiceKindService,
},
{
Service: structs.NewServiceName("db", nil),
@ -5047,6 +5048,7 @@ func TestStateStore_GatewayServices_Terminating(t *testing.T) {
CreateIndex: 21,
ModifyIndex: 21,
},
ServiceKind: structs.GatewayServiceKindService,
},
}
assert.Equal(t, expect, out)
@ -5080,6 +5082,7 @@ func TestStateStore_GatewayServices_Terminating(t *testing.T) {
CreateIndex: 21,
ModifyIndex: 21,
},
ServiceKind: structs.GatewayServiceKindService,
},
{
Service: structs.NewServiceName("db", nil),
@ -5089,6 +5092,7 @@ func TestStateStore_GatewayServices_Terminating(t *testing.T) {
CreateIndex: 21,
ModifyIndex: 21,
},
ServiceKind: structs.GatewayServiceKindService,
},
}
assert.Equal(t, expect, out)
@ -5139,6 +5143,7 @@ func TestStateStore_GatewayServices_Terminating(t *testing.T) {
CreateIndex: 22,
ModifyIndex: 22,
},
ServiceKind: structs.GatewayServiceKindService,
},
{
Service: structs.NewServiceName("db", nil),
@ -5148,6 +5153,7 @@ func TestStateStore_GatewayServices_Terminating(t *testing.T) {
CreateIndex: 22,
ModifyIndex: 22,
},
ServiceKind: structs.GatewayServiceKindService,
},
}
assert.Equal(t, expect, out)
@ -5175,6 +5181,7 @@ func TestStateStore_GatewayServices_Terminating(t *testing.T) {
CreateIndex: 22,
ModifyIndex: 22,
},
ServiceKind: structs.GatewayServiceKindService,
},
{
Service: structs.NewServiceName("db", nil),
@ -5184,6 +5191,7 @@ func TestStateStore_GatewayServices_Terminating(t *testing.T) {
CreateIndex: 22,
ModifyIndex: 22,
},
ServiceKind: structs.GatewayServiceKindService,
},
{
Service: structs.NewServiceName("redis", nil),
@ -5198,6 +5206,7 @@ func TestStateStore_GatewayServices_Terminating(t *testing.T) {
CreateIndex: 23,
ModifyIndex: 23,
},
ServiceKind: structs.GatewayServiceKindService,
},
}
assert.Equal(t, expect, out)
@ -5225,6 +5234,7 @@ func TestStateStore_GatewayServices_Terminating(t *testing.T) {
CreateIndex: 22,
ModifyIndex: 22,
},
ServiceKind: structs.GatewayServiceKindService,
},
{
Service: structs.NewServiceName("db", nil),
@ -5234,6 +5244,7 @@ func TestStateStore_GatewayServices_Terminating(t *testing.T) {
CreateIndex: 22,
ModifyIndex: 22,
},
ServiceKind: structs.GatewayServiceKindService,
},
}
assert.Equal(t, expect, out)
@ -5265,6 +5276,7 @@ func TestStateStore_GatewayServices_Terminating(t *testing.T) {
CreateIndex: 25,
ModifyIndex: 25,
},
ServiceKind: structs.GatewayServiceKindService,
},
}
assert.Equal(t, expect, out)
@ -5392,6 +5404,7 @@ func TestStateStore_GatewayServices_ServiceDeletion(t *testing.T) {
CreateIndex: 19,
ModifyIndex: 19,
},
ServiceKind: structs.GatewayServiceKindService,
},
}
assert.Equal(t, expect, out)
@ -5430,8 +5443,8 @@ func TestStateStore_GatewayServices_ServiceDeletion(t *testing.T) {
// Delete a service specified directly.
assert.Nil(t, s.DeleteService(20, "foo", "db", nil, ""))
// Only the watch for other-gateway should fire, since its association to db came from a wildcard
assert.False(t, watchFired(ws))
// The watch will fire because we need to update the gateway-services kind
assert.True(t, watchFired(ws))
assert.True(t, watchFired(otherWS))
// db should remain in the original gateway
@ -5448,7 +5461,7 @@ func TestStateStore_GatewayServices_ServiceDeletion(t *testing.T) {
CAFile: "my_ca.pem",
RaftIndex: structs.RaftIndex{
CreateIndex: 19,
ModifyIndex: 19,
ModifyIndex: 20,
},
},
}
@ -6329,6 +6342,7 @@ func TestStateStore_DumpGatewayServices(t *testing.T) {
CreateIndex: 21,
ModifyIndex: 21,
},
ServiceKind: structs.GatewayServiceKindService,
},
{
Service: structs.NewServiceName("db", nil),
@ -6338,6 +6352,7 @@ func TestStateStore_DumpGatewayServices(t *testing.T) {
CreateIndex: 21,
ModifyIndex: 21,
},
ServiceKind: structs.GatewayServiceKindService,
},
}
assert.Equal(t, expect, out)
@ -6388,6 +6403,7 @@ func TestStateStore_DumpGatewayServices(t *testing.T) {
CreateIndex: 21,
ModifyIndex: 21,
},
ServiceKind: structs.GatewayServiceKindService,
},
{
Service: structs.NewServiceName("db", nil),
@ -6397,6 +6413,7 @@ func TestStateStore_DumpGatewayServices(t *testing.T) {
CreateIndex: 21,
ModifyIndex: 21,
},
ServiceKind: structs.GatewayServiceKindService,
},
}
assert.Equal(t, expect, out)
@ -6426,6 +6443,7 @@ func TestStateStore_DumpGatewayServices(t *testing.T) {
CreateIndex: 21,
ModifyIndex: 21,
},
ServiceKind: structs.GatewayServiceKindService,
},
{
Service: structs.NewServiceName("db", nil),
@ -6435,6 +6453,7 @@ func TestStateStore_DumpGatewayServices(t *testing.T) {
CreateIndex: 21,
ModifyIndex: 21,
},
ServiceKind: structs.GatewayServiceKindService,
},
{
Service: structs.NewServiceName("redis", nil),
@ -6449,6 +6468,7 @@ func TestStateStore_DumpGatewayServices(t *testing.T) {
CreateIndex: 22,
ModifyIndex: 22,
},
ServiceKind: structs.GatewayServiceKindService,
},
}
assert.Equal(t, expect, out)
@ -6478,6 +6498,7 @@ func TestStateStore_DumpGatewayServices(t *testing.T) {
CreateIndex: 21,
ModifyIndex: 21,
},
ServiceKind: structs.GatewayServiceKindService,
},
{
Service: structs.NewServiceName("db", nil),
@ -6487,6 +6508,7 @@ func TestStateStore_DumpGatewayServices(t *testing.T) {
CreateIndex: 21,
ModifyIndex: 21,
},
ServiceKind: structs.GatewayServiceKindService,
},
}
assert.Equal(t, expect, out)
@ -6520,6 +6542,7 @@ func TestStateStore_DumpGatewayServices(t *testing.T) {
CreateIndex: 24,
ModifyIndex: 24,
},
ServiceKind: structs.GatewayServiceKindService,
},
}
assert.Equal(t, expect, out)
@ -6577,6 +6600,7 @@ func TestStateStore_DumpGatewayServices(t *testing.T) {
CreateIndex: 24,
ModifyIndex: 24,
},
ServiceKind: structs.GatewayServiceKindService,
},
{
Service: structs.NewServiceName("api", nil),

View File

@ -344,6 +344,27 @@ func deleteConfigEntryTxn(tx WriteTxn, idx uint64, kind, name string, entMeta *a
return fmt.Errorf("failed updating gateway-services index: %v", err)
}
}
c := existing.(structs.ConfigEntry)
switch x := c.(type) {
case *structs.ServiceConfigEntry:
if x.Destination != nil {
gsKind, err := GatewayServiceKind(tx, sn.Name, &sn.EnterpriseMeta)
if err != nil {
return fmt.Errorf("failed to get gateway service kind for service %s: %v", sn.Name, err)
}
if gsKind == structs.GatewayServiceKindDestination {
gsKind = structs.GatewayServiceKindUnknown
}
if err := checkGatewayWildcardsAndUpdate(tx, idx, &structs.ServiceName{Name: c.GetName(), EnterpriseMeta: *c.GetEnterpriseMeta()}, gsKind); err != nil {
return fmt.Errorf("failed updating gateway mapping: %s", err)
}
if err := checkGatewayAndUpdate(tx, idx, &structs.ServiceName{Name: c.GetName(), EnterpriseMeta: *c.GetEnterpriseMeta()}, gsKind); err != nil {
return fmt.Errorf("failed updating gateway mapping: %s", err)
}
}
}
// Also clean up associations in the mesh topology table for ingress gateways
if kind == structs.IngressGateway {
if _, err := tx.DeleteAll(tableMeshTopology, indexDownstream, sn); err != nil {
@ -376,6 +397,7 @@ func insertConfigEntryWithTxn(tx WriteTxn, idx uint64, conf structs.ConfigEntry)
}
// If the config entry is for a terminating or ingress gateway we update the memdb table
// that associates gateways <-> services.
if conf.GetKind() == structs.TerminatingGateway || conf.GetKind() == structs.IngressGateway {
err := updateGatewayServices(tx, idx, conf, conf.GetEnterpriseMeta())
if err != nil {
@ -383,6 +405,26 @@ func insertConfigEntryWithTxn(tx WriteTxn, idx uint64, conf structs.ConfigEntry)
}
}
switch conf.GetKind() {
case structs.ServiceDefaults:
if conf.(*structs.ServiceConfigEntry).Destination != nil {
sn := structs.ServiceName{Name: conf.GetName(), EnterpriseMeta: *conf.GetEnterpriseMeta()}
gsKind, err := GatewayServiceKind(tx, sn.Name, &sn.EnterpriseMeta)
if gsKind == structs.GatewayServiceKindUnknown {
gsKind = structs.GatewayServiceKindDestination
}
if err != nil {
return fmt.Errorf("failed updating gateway mapping: %s", err)
}
if err := checkGatewayWildcardsAndUpdate(tx, idx, &sn, gsKind); err != nil {
return fmt.Errorf("failed updating gateway mapping: %s", err)
}
if err := checkGatewayAndUpdate(tx, idx, &sn, gsKind); err != nil {
return fmt.Errorf("failed updating gateway mapping: %s", err)
}
}
}
// Insert the config entry and update the index
if err := tx.Insert(tableConfigEntries, conf); err != nil {
return fmt.Errorf("failed inserting config entry: %s", err)

View File

@ -73,8 +73,8 @@ func TestStore_ConfigEntry(t *testing.T) {
serviceConf.Protocol = "http"
require.NoError(t, s.EnsureConfigEntry(5, serviceConf))
require.True(t, watchFired(ws))
}
}
func TestStore_ConfigEntryCAS(t *testing.T) {
s := testConfigStateStore(t)
@ -310,6 +310,497 @@ func TestStore_ConfigEntries(t *testing.T) {
Protocol: "tcp",
}))
require.True(t, watchFired(ws))
}
func TestStore_ServiceDefaults_Kind_Destination(t *testing.T) {
s := testConfigStateStore(t)
Gtwy := &structs.TerminatingGatewayConfigEntry{
Kind: structs.TerminatingGateway,
Name: "Gtwy1",
Services: []structs.LinkedService{
{
Name: "dest1",
},
},
}
// Create
require.NoError(t, s.EnsureConfigEntry(0, Gtwy))
destination := &structs.ServiceConfigEntry{
Kind: structs.ServiceDefaults,
Name: "dest1",
Destination: &structs.DestinationConfig{},
}
_, gatewayServices, err := s.GatewayServices(nil, "Gtwy1", nil)
require.NoError(t, err)
require.Len(t, gatewayServices, 1)
require.Equal(t, gatewayServices[0].ServiceKind, structs.GatewayServiceKindUnknown)
ws := memdb.NewWatchSet()
_, _, err = s.GatewayServices(ws, "Gtwy1", nil)
require.NoError(t, err)
// Create
require.NoError(t, s.EnsureConfigEntry(0, destination))
//Watch is fired because we transitioned to a destination, by default we assume it's not.
require.True(t, watchFired(ws))
_, gatewayServices, err = s.GatewayServices(ws, "Gtwy1", nil)
require.NoError(t, err)
require.Len(t, gatewayServices, 1)
require.Equal(t, gatewayServices[0].ServiceKind, structs.GatewayServiceKindDestination)
ws = memdb.NewWatchSet()
_, _, err = s.GatewayServices(ws, "Gtwy1", nil)
require.NoError(t, err)
require.NoError(t, s.DeleteConfigEntry(6, structs.ServiceDefaults, destination.Name, &destination.EnterpriseMeta))
//Watch is fired because we transitioned to a destination, by default we assume it's not.
require.True(t, watchFired(ws))
_, gatewayServices, err = s.GatewayServices(ws, "Gtwy1", nil)
require.NoError(t, err)
require.Len(t, gatewayServices, 1)
require.Equal(t, gatewayServices[0].ServiceKind, structs.GatewayServiceKindUnknown)
}
func TestStore_ServiceDefaults_Kind_NotDestination(t *testing.T) {
s := testConfigStateStore(t)
Gtwy := &structs.TerminatingGatewayConfigEntry{
Kind: structs.TerminatingGateway,
Name: "Gtwy1",
Services: []structs.LinkedService{
{
Name: "dest1",
},
},
}
// Create
require.NoError(t, s.EnsureConfigEntry(0, Gtwy))
destination := &structs.ServiceConfigEntry{
Kind: structs.ServiceDefaults,
Name: "dest1",
}
_, gatewayServices, err := s.GatewayServices(nil, "Gtwy1", nil)
require.NoError(t, err)
require.Len(t, gatewayServices, 1)
require.Equal(t, gatewayServices[0].ServiceKind, structs.GatewayServiceKindUnknown)
ws := memdb.NewWatchSet()
_, _, err = s.GatewayServices(ws, "Gtwy1", nil)
require.NoError(t, err)
// Create
require.NoError(t, s.EnsureConfigEntry(0, destination))
//Watch is fired because we transitioned to a destination, by default we assume it's not.
require.False(t, watchFired(ws))
_, gatewayServices, err = s.GatewayServices(ws, "Gtwy1", nil)
require.NoError(t, err)
require.Len(t, gatewayServices, 1)
require.Equal(t, gatewayServices[0].ServiceKind, structs.GatewayServiceKindUnknown)
ws = memdb.NewWatchSet()
_, _, err = s.GatewayServices(ws, "Gtwy1", nil)
require.NoError(t, err)
require.NoError(t, s.DeleteConfigEntry(6, structs.ServiceDefaults, destination.Name, &destination.EnterpriseMeta))
//Watch is fired because we transitioned to a destination, by default we assume it's not.
require.False(t, watchFired(ws))
_, gatewayServices, err = s.GatewayServices(ws, "Gtwy1", nil)
require.NoError(t, err)
require.Len(t, gatewayServices, 1)
require.Equal(t, gatewayServices[0].ServiceKind, structs.GatewayServiceKindUnknown)
}
func TestStore_Service_TerminatingGateway_Kind_Service_Destination(t *testing.T) {
s := testConfigStateStore(t)
Gtwy := &structs.TerminatingGatewayConfigEntry{
Kind: structs.TerminatingGateway,
Name: "Gtwy1",
Services: []structs.LinkedService{
{
Name: "web",
},
},
}
// Create
require.NoError(t, s.EnsureConfigEntry(0, Gtwy))
service := &structs.NodeService{
Kind: structs.ServiceKindTypical,
Service: "web",
}
destination := &structs.ServiceConfigEntry{
Kind: structs.ServiceDefaults,
Name: "web",
Destination: &structs.DestinationConfig{},
}
_, gatewayServices, err := s.GatewayServices(nil, "Gtwy1", nil)
require.NoError(t, err)
require.Len(t, gatewayServices, 1)
require.Equal(t, gatewayServices[0].ServiceKind, structs.GatewayServiceKindUnknown)
ws := memdb.NewWatchSet()
_, _, err = s.GatewayServices(ws, "Gtwy1", nil)
require.NoError(t, err)
// Create
require.NoError(t, s.EnsureNode(0, &structs.Node{Node: "node1"}))
require.NoError(t, s.EnsureService(0, "node1", service))
//Watch is fired because we transitioned to a destination, by default we assume it's not.
require.True(t, watchFired(ws))
_, gatewayServices, err = s.GatewayServices(ws, "Gtwy1", nil)
require.NoError(t, err)
require.Len(t, gatewayServices, 1)
require.Equal(t, gatewayServices[0].ServiceKind, structs.GatewayServiceKindService)
require.NoError(t, s.EnsureConfigEntry(0, destination))
_, gatewayServices, err = s.GatewayServices(nil, "Gtwy1", nil)
require.NoError(t, err)
require.Len(t, gatewayServices, 1)
require.Equal(t, gatewayServices[0].ServiceKind, structs.GatewayServiceKindService)
ws = memdb.NewWatchSet()
_, _, err = s.GatewayServices(ws, "Gtwy1", nil)
require.NoError(t, err)
require.NoError(t, s.DeleteService(6, "node1", service.ID, &service.EnterpriseMeta, ""))
//Watch is fired because we transitioned to a destination, by default we assume it's not.
require.True(t, watchFired(ws))
_, gatewayServices, err = s.GatewayServices(ws, "Gtwy1", nil)
require.NoError(t, err)
require.Len(t, gatewayServices, 1)
require.Equal(t, gatewayServices[0].ServiceKind, structs.GatewayServiceKindDestination)
}
func TestStore_Service_TerminatingGateway_Kind_Destination_Service(t *testing.T) {
s := testConfigStateStore(t)
Gtwy := &structs.TerminatingGatewayConfigEntry{
Kind: structs.TerminatingGateway,
Name: "Gtwy1",
Services: []structs.LinkedService{
{
Name: "web",
},
},
}
// Create
require.NoError(t, s.EnsureConfigEntry(0, Gtwy))
service := &structs.NodeService{
Kind: structs.ServiceKindTypical,
Service: "web",
}
destination := &structs.ServiceConfigEntry{
Kind: structs.ServiceDefaults,
Name: "web",
Destination: &structs.DestinationConfig{},
}
_, gatewayServices, err := s.GatewayServices(nil, "Gtwy1", nil)
require.NoError(t, err)
require.Len(t, gatewayServices, 1)
require.Equal(t, gatewayServices[0].ServiceKind, structs.GatewayServiceKindUnknown)
ws := memdb.NewWatchSet()
_, _, err = s.GatewayServices(ws, "Gtwy1", nil)
require.NoError(t, err)
// Create
require.NoError(t, s.EnsureConfigEntry(0, destination))
_, gatewayServices, err = s.GatewayServices(nil, "Gtwy1", nil)
require.NoError(t, err)
require.Len(t, gatewayServices, 1)
require.Equal(t, gatewayServices[0].ServiceKind, structs.GatewayServiceKindDestination)
require.NoError(t, s.EnsureNode(0, &structs.Node{Node: "node1"}))
require.NoError(t, s.EnsureService(0, "node1", service))
//Watch is fired because we transitioned to a destination, by default we assume it's not.
require.True(t, watchFired(ws))
_, gatewayServices, err = s.GatewayServices(ws, "Gtwy1", nil)
require.NoError(t, err)
require.Len(t, gatewayServices, 1)
require.Equal(t, gatewayServices[0].ServiceKind, structs.GatewayServiceKindService)
ws = memdb.NewWatchSet()
_, _, err = s.GatewayServices(ws, "Gtwy1", nil)
require.NoError(t, err)
require.NoError(t, s.DeleteService(6, "node1", service.ID, &service.EnterpriseMeta, ""))
//Watch is fired because we transitioned to a destination, by default we assume it's not.
require.True(t, watchFired(ws))
_, gatewayServices, err = s.GatewayServices(ws, "Gtwy1", nil)
require.NoError(t, err)
require.Len(t, gatewayServices, 1)
require.Equal(t, gatewayServices[0].ServiceKind, structs.GatewayServiceKindDestination)
}
func TestStore_Service_TerminatingGateway_Kind_Service(t *testing.T) {
s := testConfigStateStore(t)
Gtwy := &structs.TerminatingGatewayConfigEntry{
Kind: structs.TerminatingGateway,
Name: "Gtwy1",
Services: []structs.LinkedService{
{
Name: "web",
},
},
}
// Create
require.NoError(t, s.EnsureConfigEntry(0, Gtwy))
service := &structs.NodeService{
Kind: structs.ServiceKindTypical,
Service: "web",
}
_, gatewayServices, err := s.GatewayServices(nil, "Gtwy1", nil)
require.NoError(t, err)
require.Len(t, gatewayServices, 1)
require.Equal(t, gatewayServices[0].ServiceKind, structs.GatewayServiceKindUnknown)
ws := memdb.NewWatchSet()
_, _, err = s.GatewayServices(ws, "Gtwy1", nil)
require.NoError(t, err)
// Create
require.NoError(t, s.EnsureNode(0, &structs.Node{Node: "node1"}))
require.NoError(t, s.EnsureService(0, "node1", service))
//Watch is fired because we transitioned to a destination, by default we assume it's not.
require.True(t, watchFired(ws))
_, gatewayServices, err = s.GatewayServices(ws, "Gtwy1", nil)
require.NoError(t, err)
require.Len(t, gatewayServices, 1)
require.Equal(t, gatewayServices[0].ServiceKind, structs.GatewayServiceKindService)
ws = memdb.NewWatchSet()
_, _, err = s.GatewayServices(ws, "Gtwy1", nil)
require.NoError(t, err)
require.NoError(t, s.DeleteService(6, "node1", service.ID, &service.EnterpriseMeta, ""))
//Watch is fired because we transitioned to a destination, by default we assume it's not.
require.True(t, watchFired(ws))
_, gatewayServices, err = s.GatewayServices(ws, "Gtwy1", nil)
require.NoError(t, err)
require.Len(t, gatewayServices, 1)
require.Equal(t, gatewayServices[0].ServiceKind, structs.GatewayServiceKindUnknown)
}
func TestStore_ServiceDefaults_Kind_Destination_Wildcard(t *testing.T) {
s := testConfigStateStore(t)
Gtwy := &structs.TerminatingGatewayConfigEntry{
Kind: structs.TerminatingGateway,
Name: "Gtwy1",
Services: []structs.LinkedService{
{
Name: "*",
},
},
}
// Create
require.NoError(t, s.EnsureConfigEntry(0, Gtwy))
destination := &structs.ServiceConfigEntry{
Kind: structs.ServiceDefaults,
Name: "dest1",
Destination: &structs.DestinationConfig{},
}
_, gatewayServices, err := s.GatewayServices(nil, "Gtwy1", nil)
require.NoError(t, err)
require.Len(t, gatewayServices, 0)
ws := memdb.NewWatchSet()
_, _, err = s.GatewayServices(ws, "Gtwy1", nil)
// Create
require.NoError(t, s.EnsureConfigEntry(0, destination))
require.NoError(t, err)
require.True(t, watchFired(ws))
_, gatewayServices, err = s.GatewayServices(ws, "Gtwy1", nil)
require.NoError(t, err)
require.Len(t, gatewayServices, 1)
require.Equal(t, gatewayServices[0].ServiceKind, structs.GatewayServiceKindDestination)
ws = memdb.NewWatchSet()
_, _, err = s.GatewayServices(ws, "Gtwy1", nil)
require.NoError(t, err)
require.NoError(t, s.DeleteConfigEntry(6, structs.ServiceDefaults, destination.Name, &destination.EnterpriseMeta))
//Watch is fired because we transitioned to a destination, by default we assume it's not.
require.True(t, watchFired(ws))
_, gatewayServices, err = s.GatewayServices(ws, "Gtwy1", nil)
require.NoError(t, err)
require.Len(t, gatewayServices, 1)
require.Equal(t, gatewayServices[0].ServiceKind, structs.GatewayServiceKindUnknown)
}
func TestStore_Service_TerminatingGateway_Kind_Service_Wildcard(t *testing.T) {
s := testConfigStateStore(t)
Gtwy := &structs.TerminatingGatewayConfigEntry{
Kind: structs.TerminatingGateway,
Name: "Gtwy1",
Services: []structs.LinkedService{
{
Name: "*",
},
},
}
// Create
require.NoError(t, s.EnsureConfigEntry(0, Gtwy))
service := &structs.NodeService{
Kind: structs.ServiceKindTypical,
Service: "web",
}
_, gatewayServices, err := s.GatewayServices(nil, "Gtwy1", nil)
require.NoError(t, err)
require.Len(t, gatewayServices, 0)
ws := memdb.NewWatchSet()
_, _, err = s.GatewayServices(ws, "Gtwy1", nil)
require.NoError(t, err)
// Create
require.NoError(t, s.EnsureNode(0, &structs.Node{Node: "node1"}))
require.NoError(t, s.EnsureService(0, "node1", service))
//Watch is fired because we transitioned to a destination, by default we assume it's not.
require.True(t, watchFired(ws))
_, gatewayServices, err = s.GatewayServices(ws, "Gtwy1", nil)
require.NoError(t, err)
require.Len(t, gatewayServices, 1)
require.Equal(t, gatewayServices[0].ServiceKind, structs.GatewayServiceKindService)
ws = memdb.NewWatchSet()
_, _, err = s.GatewayServices(ws, "Gtwy1", nil)
require.NoError(t, err)
require.NoError(t, s.DeleteService(6, "node1", service.ID, &service.EnterpriseMeta, ""))
//Watch is fired because we transitioned to a destination, by default we assume it's not.
require.True(t, watchFired(ws))
_, gatewayServices, err = s.GatewayServices(ws, "Gtwy1", nil)
require.NoError(t, err)
require.Len(t, gatewayServices, 0)
}
func TestStore_Service_TerminatingGateway_Kind_Service_Destination_Wildcard(t *testing.T) {
s := testConfigStateStore(t)
Gtwy := &structs.TerminatingGatewayConfigEntry{
Kind: structs.TerminatingGateway,
Name: "Gtwy1",
Services: []structs.LinkedService{
{
Name: "*",
},
},
}
// Create
require.NoError(t, s.EnsureConfigEntry(0, Gtwy))
service := &structs.NodeService{
Kind: structs.ServiceKindTypical,
Service: "web",
}
destination := &structs.ServiceConfigEntry{
Kind: structs.ServiceDefaults,
Name: "web",
Destination: &structs.DestinationConfig{},
}
_, gatewayServices, err := s.GatewayServices(nil, "Gtwy1", nil)
require.NoError(t, err)
require.Len(t, gatewayServices, 0)
ws := memdb.NewWatchSet()
_, _, err = s.GatewayServices(ws, "Gtwy1", nil)
require.NoError(t, err)
// Create
require.NoError(t, s.EnsureConfigEntry(0, destination))
_, gatewayServices, err = s.GatewayServices(nil, "Gtwy1", nil)
require.NoError(t, err)
require.Len(t, gatewayServices, 1)
require.Equal(t, gatewayServices[0].ServiceKind, structs.GatewayServiceKindDestination)
require.NoError(t, s.EnsureNode(0, &structs.Node{Node: "node1"}))
require.NoError(t, s.EnsureService(0, "node1", service))
//Watch is fired because we transitioned to a destination, by default we assume it's not.
require.True(t, watchFired(ws))
_, gatewayServices, err = s.GatewayServices(ws, "Gtwy1", nil)
require.NoError(t, err)
require.Len(t, gatewayServices, 1)
require.Equal(t, gatewayServices[0].ServiceKind, structs.GatewayServiceKindService)
ws = memdb.NewWatchSet()
_, _, err = s.GatewayServices(ws, "Gtwy1", nil)
require.NoError(t, err)
require.NoError(t, s.DeleteService(6, "node1", service.ID, &service.EnterpriseMeta, ""))
//Watch is fired because we transitioned to a destination, by default we assume it's not.
require.True(t, watchFired(ws))
_, gatewayServices, err = s.GatewayServices(ws, "Gtwy1", nil)
require.NoError(t, err)
require.Len(t, gatewayServices, 0)
}
func TestStore_ConfigEntry_GraphValidation(t *testing.T) {

View File

@ -105,7 +105,7 @@ type ServiceConfigEntry struct {
Expose ExposeConfig `json:",omitempty"`
ExternalSNI string `json:",omitempty" alias:"external_sni"`
UpstreamConfig *UpstreamConfiguration `json:",omitempty" alias:"upstream_config"`
Endpoint *EndpointConfig `json:",omitempty"`
Destination *DestinationConfig `json:",omitempty"`
MaxInboundConnections int `json:",omitempty" alias:"max_inbound_connections"`
Meta map[string]string `json:",omitempty"`
@ -180,8 +180,8 @@ func (e *ServiceConfigEntry) Validate() error {
validationErr := validateConfigEntryMeta(e.Meta)
// External endpoints are invalid with an existing service's upstream configuration
if e.UpstreamConfig != nil && e.Endpoint != nil {
validationErr = multierror.Append(validationErr, errors.New("UpstreamConfig and Endpoint are mutually exclusive for service defaults"))
if e.UpstreamConfig != nil && e.Destination != nil {
validationErr = multierror.Append(validationErr, errors.New("UpstreamConfig and Destination are mutually exclusive for service defaults"))
return validationErr
}
@ -200,13 +200,13 @@ func (e *ServiceConfigEntry) Validate() error {
}
}
if e.Endpoint != nil {
if err := validateEndpointAddress(e.Endpoint.Address); err != nil {
validationErr = multierror.Append(validationErr, fmt.Errorf("Endpoint address is invalid %w", err))
if e.Destination != nil {
if err := validateEndpointAddress(e.Destination.Address); err != nil {
validationErr = multierror.Append(validationErr, fmt.Errorf("Destination address is invalid %w", err))
}
if e.Endpoint.Port < 1 || e.Endpoint.Port > 65535 {
validationErr = multierror.Append(validationErr, fmt.Errorf("Invalid Port number %d", e.Endpoint.Port))
if e.Destination.Port < 1 || e.Destination.Port > 65535 {
validationErr = multierror.Append(validationErr, fmt.Errorf("Invalid Port number %d", e.Destination.Port))
}
}
@ -292,8 +292,8 @@ func (c *UpstreamConfiguration) Clone() *UpstreamConfiguration {
return &c2
}
// EndpointConfig represents a virtual service, i.e. one that is external to Consul
type EndpointConfig struct {
// DestinationConfig represents a virtual service, i.e. one that is external to Consul
type DestinationConfig struct {
// Address of the endpoint; hostname, IP, or CIDR
Address string `json:",omitempty"`

View File

@ -586,19 +586,28 @@ func (e *TerminatingGatewayConfigEntry) Warnings() []string {
return warnings
}
type GatewayServiceKind string
const (
GatewayServiceKindUnknown GatewayServiceKind = ""
GatewayServiceKindDestination GatewayServiceKind = "destination"
GatewayServiceKindService GatewayServiceKind = "service"
)
// GatewayService is used to associate gateways with their linked services.
type GatewayService struct {
Gateway ServiceName
Service ServiceName
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"`
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"`
ServiceKind GatewayServiceKind `json:",omitempty"`
RaftIndex
}
@ -635,6 +644,7 @@ func (g *GatewayService) IsSame(o *GatewayService) bool {
g.CertFile == o.CertFile &&
g.KeyFile == o.KeyFile &&
g.SNI == o.SNI &&
g.ServiceKind == o.ServiceKind &&
g.FromWildcard == o.FromWildcard
}
@ -653,5 +663,6 @@ func (g *GatewayService) Clone() *GatewayService {
SNI: g.SNI,
FromWildcard: g.FromWildcard,
RaftIndex: g.RaftIndex,
ServiceKind: g.ServiceKind,
}
}

View File

@ -428,12 +428,12 @@ func TestDecodeConfigEntry(t *testing.T) {
},
},
{
name: "service-defaults-with-endpoint",
name: "service-defaults-with-destination",
snake: `
kind = "service-defaults"
name = "external"
protocol = "tcp"
endpoint {
destination {
address = "1.2.3.4/24"
port = 8080
}
@ -442,7 +442,7 @@ func TestDecodeConfigEntry(t *testing.T) {
Kind = "service-defaults"
Name = "external"
Protocol = "tcp"
Endpoint {
Destination {
Address = "1.2.3.4/24"
Port = 8080
}
@ -451,7 +451,7 @@ func TestDecodeConfigEntry(t *testing.T) {
Kind: "service-defaults",
Name: "external",
Protocol: "tcp",
Endpoint: &EndpointConfig{
Destination: &DestinationConfig{
Address: "1.2.3.4/24",
Port: 8080,
},
@ -2421,79 +2421,79 @@ func TestServiceConfigEntry(t *testing.T) {
EnterpriseMeta: *DefaultEnterpriseMetaInDefaultPartition(),
},
},
"validate: missing endpoint address": {
"validate: missing destination address": {
entry: &ServiceConfigEntry{
Kind: ServiceDefaults,
Name: "external",
Protocol: "tcp",
Endpoint: &EndpointConfig{
Destination: &DestinationConfig{
Address: "",
Port: 443,
},
},
validateErr: "Could not validate address",
},
"validate: endpoint ipv4 address": {
"validate: destination ipv4 address": {
entry: &ServiceConfigEntry{
Kind: ServiceDefaults,
Name: "external",
Protocol: "tcp",
Endpoint: &EndpointConfig{
Destination: &DestinationConfig{
Address: "1.2.3.4",
Port: 443,
},
},
},
"validate: endpoint ipv4 CIDR address": {
"validate: destination ipv4 CIDR address": {
entry: &ServiceConfigEntry{
Kind: ServiceDefaults,
Name: "external",
Protocol: "tcp",
Endpoint: &EndpointConfig{
Destination: &DestinationConfig{
Address: "10.0.0.1/16",
Port: 8080,
},
},
},
"validate: endpoint ipv6 address": {
"validate: destination ipv6 address": {
entry: &ServiceConfigEntry{
Kind: ServiceDefaults,
Name: "external",
Protocol: "tcp",
Endpoint: &EndpointConfig{
Destination: &DestinationConfig{
Address: "2001:0db8:0000:8a2e:0370:7334:1234:5678",
Port: 443,
},
},
},
"valid endpoint shortened ipv6 address": {
"valid destination shortened ipv6 address": {
entry: &ServiceConfigEntry{
Kind: ServiceDefaults,
Name: "external",
Protocol: "tcp",
Endpoint: &EndpointConfig{
Destination: &DestinationConfig{
Address: "2001:db8::8a2e:370:7334",
Port: 443,
},
},
},
"validate: endpoint ipv6 CIDR address": {
"validate: destination ipv6 CIDR address": {
entry: &ServiceConfigEntry{
Kind: ServiceDefaults,
Name: "external",
Protocol: "tcp",
Endpoint: &EndpointConfig{
Destination: &DestinationConfig{
Address: "2001:db8::8a2e:370:7334/64",
Port: 443,
},
},
},
"validate: invalid endpoint port": {
"validate: invalid destination port": {
entry: &ServiceConfigEntry{
Kind: ServiceDefaults,
Name: "external",
Protocol: "tcp",
Endpoint: &EndpointConfig{
Destination: &DestinationConfig{
Address: "2001:db8::8a2e:370:7334/64",
},
},
@ -2504,7 +2504,7 @@ func TestServiceConfigEntry(t *testing.T) {
Kind: ServiceDefaults,
Name: "external",
Protocol: "tcp",
Endpoint: &EndpointConfig{
Destination: &DestinationConfig{
Address: "*external.com",
Port: 443,
},
@ -2516,7 +2516,7 @@ func TestServiceConfigEntry(t *testing.T) {
Kind: ServiceDefaults,
Name: "external",
Protocol: "tcp",
Endpoint: &EndpointConfig{
Destination: &DestinationConfig{
Address: "..hello.",
Port: 443,
},
@ -2528,7 +2528,7 @@ func TestServiceConfigEntry(t *testing.T) {
Kind: ServiceDefaults,
Name: "external",
Protocol: "http",
Endpoint: &EndpointConfig{
Destination: &DestinationConfig{
Address: "*",
Port: 443,
},

View File

@ -179,8 +179,8 @@ type UpstreamConfig struct {
MeshGateway MeshGatewayConfig `json:",omitempty" alias:"mesh_gateway" `
}
// EndpointConfig represents a virtual service, i.e. one that is external to Consul
type EndpointConfig struct {
// DestinationConfig represents a virtual service, i.e. one that is external to Consul
type DestinationConfig struct {
// Address of the endpoint; hostname, IP, or CIDR
Address string `json:",omitempty"`
@ -229,7 +229,7 @@ type ServiceConfigEntry struct {
Expose ExposeConfig `json:",omitempty"`
ExternalSNI string `json:",omitempty" alias:"external_sni"`
UpstreamConfig *UpstreamConfiguration `json:",omitempty" alias:"upstream_config"`
Endpoint *EndpointConfig `json:",omitempty"`
Destination *DestinationConfig `json:",omitempty"`
Meta map[string]string `json:",omitempty"`
CreateIndex uint64
ModifyIndex uint64

View File

@ -106,16 +106,16 @@ func TestAPI_ConfigEntries(t *testing.T) {
},
}
endpoint := &EndpointConfig{
dest := &DestinationConfig{
Address: "my.example.com",
Port: 80,
}
service2 := &ServiceConfigEntry{
Kind: ServiceDefaults,
Name: "bar",
Protocol: "tcp",
Endpoint: endpoint,
Kind: ServiceDefaults,
Name: "bar",
Protocol: "tcp",
Destination: dest,
}
// set it
@ -191,7 +191,7 @@ func TestAPI_ConfigEntries(t *testing.T) {
require.Equal(t, service2.Kind, readService.Kind)
require.Equal(t, service2.Name, readService.Name)
require.Equal(t, service2.Protocol, readService.Protocol)
require.Equal(t, endpoint, readService.Endpoint)
require.Equal(t, dest, readService.Destination)
}
}
@ -530,7 +530,7 @@ func TestDecodeConfigEntry(t *testing.T) {
"Kind": "service-defaults",
"Name": "external",
"Protocol": "http",
"Endpoint": {
"Destination": {
"Address": "1.2.3.4/24",
"Port": 443
}
@ -540,7 +540,7 @@ func TestDecodeConfigEntry(t *testing.T) {
Kind: "service-defaults",
Name: "external",
Protocol: "http",
Endpoint: &EndpointConfig{
Destination: &DestinationConfig{
Address: "1.2.3.4/24",
Port: 443,
},

View File

@ -793,7 +793,7 @@ func TestParseConfigEntry(t *testing.T) {
},
},
{
name: "service-defaults: kitchen sink (endpoint edition)",
name: "service-defaults: kitchen sink (destination edition)",
snake: `
kind = "service-defaults"
name = "main"
@ -810,7 +810,7 @@ func TestParseConfigEntry(t *testing.T) {
outbound_listener_port = 10101
dialed_directly = true
}
endpoint = {
destination = {
address = "10.0.0.0/16",
port = 443
}
@ -831,7 +831,7 @@ func TestParseConfigEntry(t *testing.T) {
outbound_listener_port = 10101
dialed_directly = true
}
Endpoint = {
Destination = {
Address = "10.0.0.0/16",
Port = 443
}
@ -853,7 +853,7 @@ func TestParseConfigEntry(t *testing.T) {
"outbound_listener_port": 10101,
"dialed_directly": true
},
"endpoint": {
"destination": {
"address": "10.0.0.0/16",
"port": 443
}
@ -876,7 +876,7 @@ func TestParseConfigEntry(t *testing.T) {
"OutboundListenerPort": 10101,
"DialedDirectly": true
},
"Endpoint": {
"Destination": {
"Address": "10.0.0.0/16",
"Port": 443
}
@ -898,7 +898,7 @@ func TestParseConfigEntry(t *testing.T) {
OutboundListenerPort: 10101,
DialedDirectly: true,
},
Endpoint: &api.EndpointConfig{
Destination: &api.DestinationConfig{
Address: "10.0.0.0/16",
Port: 443,
},