diff --git a/changelog/11084.txt b/changelog/11084.txt new file mode 100644 index 0000000000..444c93da99 --- /dev/null +++ b/changelog/11084.txt @@ -0,0 +1,3 @@ +```release-note:improvement +serviceregistration: Added support for Consul ServiceMeta tags from config file from the new `service_meta` config field. +``` diff --git a/serviceregistration/consul/consul_service_registration.go b/serviceregistration/consul/consul_service_registration.go index c59ed775cc..f3830121ae 100644 --- a/serviceregistration/consul/consul_service_registration.go +++ b/serviceregistration/consul/consul_service_registration.go @@ -5,6 +5,7 @@ package consul import ( "context" + "encoding/json" "errors" "fmt" "math/rand" @@ -73,6 +74,7 @@ type serviceRegistration struct { redirectPort int64 serviceName string serviceTags []string + serviceMeta map[string]string serviceAddress *string disableRegistration bool checkTimeout time.Duration @@ -229,6 +231,18 @@ func (c *serviceRegistration) merge(conf map[string]string) error { c.logger.Debug("config service_tags set", "service_tags", tags) } + // Get user-defined meta tags to attach to the registered service name + metaTags := map[string]string{} + if metaTagsJSON, ok := conf["service_meta"]; ok { + if err := json.Unmarshal([]byte(metaTagsJSON), &metaTags); err != nil { + return errors.New("service tags must be a dictionary of string keys and values") + } + } + metaTags["external-source"] = metaExternalSource + if c.logger.IsDebug() { + c.logger.Debug("config service_meta set", "service_meta", metaTags) + } + // Get the service-specific address to override the use of the HA redirect address var serviceAddr *string serviceAddrStr, ok := conf["service_address"] @@ -294,6 +308,7 @@ func (c *serviceRegistration) merge(conf map[string]string) error { c.config = consulConf c.serviceName = service c.serviceTags = strutil.ParseDedupAndSortStrings(tags, ",") + c.serviceMeta = metaTags c.serviceAddress = serviceAddr c.checkTimeout = checkTimeout c.disableRegistration = disableRegistration @@ -586,12 +601,10 @@ func (c *serviceRegistration) reconcileConsul() (serviceID string, err error) { ID: serviceID, Name: c.serviceName, Tags: tags, + Meta: c.serviceMeta, Port: int(c.redirectPort), Address: serviceAddress, EnableTagOverride: false, - Meta: map[string]string{ - "external-source": metaExternalSource, - }, } checkStatus := api.HealthCritical diff --git a/serviceregistration/consul/consul_service_registration_test.go b/serviceregistration/consul/consul_service_registration_test.go index 8dcc3d6695..c728e721c1 100644 --- a/serviceregistration/consul/consul_service_registration_test.go +++ b/serviceregistration/consul/consul_service_registration_test.go @@ -492,6 +492,66 @@ func TestConsul_serviceTags(t *testing.T) { } } +// TestConsul_ServiceMeta tests whether consul service meta registration works +func TestConsul_ServiceMeta(t *testing.T) { + tests := []struct { + conf map[string]string + pass bool + expect map[string]string + }{ + { + conf: map[string]string{}, + pass: true, + expect: map[string]string{"external-source": "vault"}, + }, + { + conf: map[string]string{"service_meta": "true"}, + pass: false, + expect: map[string]string{"external-source": "vault"}, + }, + { + conf: map[string]string{"service_meta": "{\"key\":\"value\"}"}, + pass: true, + expect: map[string]string{"key": "value", "external-source": "vault"}, + }, + { + conf: map[string]string{"service_meta": "{\"external-source\":\"something-else\"}"}, + pass: true, + expect: map[string]string{"external-source": "vault"}, + }, + } + + for _, test := range tests { + logger := logging.NewVaultLogger(log.Debug) + + shutdownCh := make(chan struct{}) + defer func() { + close(shutdownCh) + }() + sr, err := NewServiceRegistration(test.conf, logger, sr.State{}) + if !test.pass { + if err == nil { + t.Fatal("Expected Consul to fail with error") + } + continue + } + + if err != nil && test.pass { + t.Fatalf("Expected Consul to initialize: %v", err) + } + + c, ok := sr.(*serviceRegistration) + if !ok { + t.Fatalf("Expected serviceRegistration") + } + + if !reflect.DeepEqual(c.serviceMeta, test.expect) { + t.Fatalf("Did not produce expected meta: wanted: %v, got %v", test.expect, c.serviceMeta) + } + + } +} + func TestConsul_setRedirectAddr(t *testing.T) { tests := []struct { addr string diff --git a/website/content/docs/configuration/service-registration/consul.mdx b/website/content/docs/configuration/service-registration/consul.mdx index bd73ce7e59..b956d748fe 100644 --- a/website/content/docs/configuration/service-registration/consul.mdx +++ b/website/content/docs/configuration/service-registration/consul.mdx @@ -85,6 +85,9 @@ at Consul's service discovery layer. - `service_tags` `(string: "")` – Specifies a comma-separated list of case-sensitive tags to attach to the service registration in Consul. +- `service_meta` `(map[string]string: {})` – Specifies a key-value list of meta tags to + attach to the service registration in Consul. See [ServiceMeta](/consul/api-docs/catalog#servicemeta) in the Consul docs for more information. + - `service_address` `(string: nil)` – Specifies a service-specific address to set on the service registration in Consul. If unset, Vault will use what it knows to be the HA redirect address - which is usually desirable. Setting diff --git a/website/content/docs/configuration/storage/consul.mdx b/website/content/docs/configuration/storage/consul.mdx index 073f73633e..939db3971b 100644 --- a/website/content/docs/configuration/storage/consul.mdx +++ b/website/content/docs/configuration/storage/consul.mdx @@ -92,6 +92,9 @@ and [`cluster_addr`][cluster-addr] ([example][listener-example]). - `service_tags` `(string: "")` – Specifies a comma-separated list of tags to attach to the service registration in Consul. +- `service_meta` `(map[string]string: {})` – Specifies a key-value list of meta tags to + attach to the service registration in Consul. See [ServiceMeta](/consul/api-docs/catalog#servicemeta) in the Consul docs for more information. + - `service_address` `(string: nil)` – Specifies a service-specific address to set on the service registration in Consul. If unset, Vault will use what it knows to be the HA redirect address - which is usually desirable. Setting