Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow setting of Consul ServiceMeta tags from config file #11084

Merged
merged 7 commits into from
May 27, 2024
Merged

Allow setting of Consul ServiceMeta tags from config file #11084

merged 7 commits into from
May 27, 2024

Conversation

unRob
Copy link
Contributor

@unRob unRob commented Mar 11, 2021

Hi there!

I'd love to be able to set ServiceMeta on the Consul service registered by Vault by specifying the desired tags in the config file, and I'm submitting this PR to that effect.

I'm not happy about unmarshalling json during NewServiceRegistration but considered that a simpler change than the couple of alternatives I came up from a quick glance at the codebase. That is to say, I'd love feedback on the approach (and perhaps suggestions on a proper testing strategy should folks feel this approach works).

fixes #9121
see also #10233

@hashicorp-cla
Copy link

hashicorp-cla commented Mar 11, 2021

CLA assistant check
All committers have signed the CLA.

@unRob
Copy link
Contributor Author

unRob commented Jun 24, 2023

Still very interested in seeing this through, any chance it could be reviewed?

@unRob unRob requested a review from a team as a code owner October 6, 2023 04:29
@schavis schavis added the content-lgtm Content changes approved. Merge depends on code review label Oct 9, 2023
@schavis schavis removed the request for review from yhyakuna October 9, 2023 19:54
@schavis schavis added the needs-eng-review Community PR waiting for ENG review label Oct 9, 2023
@schavis schavis removed the request for review from a team February 22, 2024 00:30
@VioletHynes
Copy link
Contributor

Hey there @unRob ! I'm really very sorry this one has waited so long, but I'm pretty eager to get it merged in as long as you are.

There's just a few things I'd like to confirm/address before we do. I'll be leaving a review shortly with some comments, but I'll be watching this closely for updates, and please feel free to tag me just in case :)

Copy link
Contributor

@VioletHynes VioletHynes left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for bearing with us on this. A few comments and things I'd like to see answered/addressed, but I'm eager to get this merged. I agree that the approach of deserializing the JSON where you have seems to be the easiest place and I don't see it as too problematic.

I know this took a while to be reviewed but I'm committed to helping you see this to the finish line, as long as you're still willing :)

pass: false,
},
{
conf: map[string]string{"service_meta": "[{\"key\":\"value\"}]"},
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How come the config must be a list? Since we're only taking the first of these values, I'd expect to be able to configure this as a set of JSON strings, e.g.

conf: map[string]string{"service_meta": "{\"key\":\"value\", \"bar\":\"baz\"}"},

Comment on lines 239 to 244
metaTagList := []map[string]string{}
err := json.Unmarshal([]byte(metaTagsJSON), &metaTagList)
if err != nil {
return nil, errors.New("service tags must be a dictionary of string keys and values")
}
metaTags = metaTagList[0]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As mentioned elsewhere, I'm a little confused why we're unmarshaling this into a list first and then taking the first element. Could this be changed so that we don't expect a list?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't recall why I made this choice in the context of the codebase I originally submitted this PR to, but agree it does not make any sense at all as in config, these values—as part of storage or service_registration— will be maps. Vaguely remember having trouble understanding if I should be using HCL blocks or objects.

I think my original intention was to allow something like the following config snippet

storage "consul" {
  service_meta = {some_key = "some value"}
}

It's been a while, and I eventually ended up hacking around this shortcoming, so don't really have an informed opinion. Fixing.

Comment on lines 246 to 245
if logger.IsDebug() {
logger.Debug("config service_meta set", "service_meta", metaTags)
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
if logger.IsDebug() {
logger.Debug("config service_meta set", "service_meta", metaTags)
}
c.logger.Debug("config service_meta set", "service_meta", metaTags)

@@ -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.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think an example here would be great

website/content/docs/configuration/storage/consul.mdx Outdated Show resolved Hide resolved
@@ -229,6 +232,22 @@ 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
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The formatting looks a little strange here -- could you give this a make fmt/align this?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, I used github's UI to resolve the refactor of NewServiceRegistration / serverRegistration.merge and did not really pay attention, while I had hope, I was not really expecting someone to bring this PR back from the dead 😂 . Fixing!

metaTagList := []map[string]string{}
err := json.Unmarshal([]byte(metaTagsJSON), &metaTagList)
if err != nil {
return nil, errors.New("service tags must be a dictionary of string keys and values")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It seems the code has changed around this, and this should just be
return errors.New("service tags must be a dictionary of string keys and values")

@VioletHynes
Copy link
Contributor

VioletHynes commented May 27, 2024

Oh, one last thing, we would require a changelog for this. I'm happy to do it myself if you don't want to fiddle, but it'd be a file in the changelog directory called 11084.txt with something like the following text:

```release-note:improvement
serviceregistration: Added support for Consul ServiceMeta tags from config file from the new `service_meta` config field.
-```

(Delete the - preceding the three backticks, I couldn't get it to format properly otherwise. The other changelogs in that directory should show you the right formatting though)

@unRob unRob requested a review from VioletHynes May 27, 2024 17:53
Copy link
Contributor

@VioletHynes VioletHynes left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks great! Just a few more things before we can get this over the finish line. Thanks for the quick response so far!

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
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should do this irrespective of if ok, since otherwise there will be a behaviour change as part of this PR. Previously, the tag would have been set, but now, it won't be set unless I provide my own meta tags.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To put it another way: if I don't provide my own service_meta, it should still be:

map[string]string{
	"external-source": metaExternalSource,
},

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd suggest moving this line until after the if ok, that way the behaviour is preserved.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

good catch, fixed!

@@ -492,6 +492,43 @@ func TestConsul_serviceTags(t *testing.T) {
}
}

func TestConsul_serviceMeta(t *testing.T) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: We should have a godoc describing what this test does and is about

@@ -492,6 +492,43 @@ func TestConsul_serviceTags(t *testing.T) {
}
}

func TestConsul_serviceMeta(t *testing.T) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
func TestConsul_serviceMeta(t *testing.T) {
func TestConsul_ServiceMeta(t *testing.T) {

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd love to see a test in some respect here that validates that if I don't provide my own service_meta, that it's still set to what it was before ("external-source": metaExternalSource)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One way we could do this is by improving TestConsul_ServiceMeta to test the resultant map for the three configurations, but I'm open to whatever you feel is easiest :)

Copy link
Contributor

@VioletHynes VioletHynes left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you! I appreciate your patience for bearing with us on this, but thanks for being so understanding and great to work with. Approved! I'll look to get this merged as soon as all the CI passes etc.

@VioletHynes VioletHynes merged commit 6e72397 into hashicorp:main May 27, 2024
67 of 68 checks passed
@unRob unRob deleted the consul-meta-tags branch May 28, 2024 06:34
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
content-lgtm Content changes approved. Merge depends on code review ecosystem needs-eng-review Community PR waiting for ENG review
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Add Metadata to Service Registration in Consul
5 participants