Skip to content

feat: Add Consul KV integration for template variables (GH-473)#850

Draft
DeekshithaTimmareddy wants to merge 9 commits into
mainfrom
feat/consul-kv-integration-gh-473
Draft

feat: Add Consul KV integration for template variables (GH-473)#850
DeekshithaTimmareddy wants to merge 9 commits into
mainfrom
feat/consul-kv-integration-gh-473

Conversation

@DeekshithaTimmareddy

@DeekshithaTimmareddy DeekshithaTimmareddy commented Mar 23, 2026

Copy link
Copy Markdown
Collaborator

Description

Adds support for retrieving variables from Consul's Key-Value store in pack templates, addressing feature request #473.

This implementation adds two new template functions:

  • consulKey(key) - Retrieves a single key-value pair
  • consulKeys(prefix) - Retrieves multiple key-value pairs with a given prefix

Currently, variables must be provided via CLI or files, which can be limiting for dynamic configurations. This feature enables packs to fetch configuration directly from Consul KV, similar to the existing Nomad Variables integration.

Changes

  • Added consulKey() and consulKeys() template functions
  • Added ConsulClient field to Renderer struct
  • Updated CLI commands (run, plan, render) to support Consul KV flags:
    • --consul-kv-address - Consul server address
    • --consul-kv-token - Consul ACL token
    • --consul-kv-namespace - Consul namespace (Enterprise)
  • Added comprehensive documentation in docs/functions.md
  • Updated go.mod to include Consul API as direct dependency

Testing Steps

  1. Start Consul and checking if it is already running on Mac
image
  1. Adding test data to Consul
image
  1. Verifying data in Consul
image
  1. Creating and verifying a test pack
image

Building the nomad-pack and verifying the flag exists

image

After creating variables.hcl and metadata.hcl files

image

Successful render

Test - Error Handling

image

wrong port(9999) gave clear error which shows proper error handling when Consul is unavailable

Reminders

  • Add CHANGELOG.md entry
  • If a change needs to be reverted, we will roll out an update to the code within 7 days.

Changes to Security Controls

Are there any changes to security controls (access controls, encryption, logging) in this pull request? If so, explain.

@DeekshithaTimmareddy DeekshithaTimmareddy force-pushed the feat/consul-kv-integration-gh-473 branch from 0f45210 to 6e6da00 Compare March 23, 2026 12:23
@DeekshithaTimmareddy DeekshithaTimmareddy marked this pull request as ready for review March 25, 2026 14:07
@DeekshithaTimmareddy DeekshithaTimmareddy requested review from a team as code owners March 25, 2026 14:07
- Add consulKey() and consulKeys() template functions to access Consul KV store
- Add --consul-kv-address, --consul-kv-token, --consul-kv-namespace flags to run, plan, and render commands
- Update PackManager and Renderer to support Consul client
- Add comprehensive documentation with examples
- Follows same pattern as existing Nomad Variables integration

Implements #473
@DeekshithaTimmareddy DeekshithaTimmareddy force-pushed the feat/consul-kv-integration-gh-473 branch from 6e6da00 to 6cd6fa5 Compare March 26, 2026 12:06

@jrasell jrasell left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Thanks for the changes @TIMMAREDDYDEEKSHITHA-ship-it! There is still a bit of code duplication I think we can tidy up. It would also be good to think about what tests we can add as part of this PR, as currently, we are adding ~600 LOC without one test.

Comment thread CHANGELOG.md Outdated
Comment thread internal/cli/plan.go Outdated
Comment thread internal/cli/plan.go Outdated

@jrasell jrasell left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

The Consul client setup is slightly duplicated in the run, plan, and render commands. It'll be good to use a single helper function that is called to generate a client if needed, that includes all the config parsing and precedence handling.

In the documentation it's probably a good idea to call out that the presence of the Consul address indicates Nomad Pack will attempt to generate an API client.

The manual testing steps are great, but this doesn't cover automated CI and adds additional manual overhead on all code review. It would also be great to have some minimal tests to cover the Consul API functionality. I think there are a few possibilities here:

  • have a basic test HTTP server that can be used to mock the Consul API and return data
  • run Consul in dev mode via helper scripts, populate with data in the test
  • check if Consul has a similar HTTP test agent that can be used in tests

Comment thread internal/cli/helpers.go Outdated
Comment thread internal/cli/helpers_consul_test.go Outdated

@jrasell jrasell left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Thanks @TIMMAREDDYDEEKSHITHA-ship-it, I think this is getting close. Along with some inline comments, it would be really good to have some additional testing of the new code, including the template functions (via a mocked http server).

Comment thread internal/cli/helpers.go
}

// Package-level variable to track if Consul flags have been registered
var consulFlagsRegistered = false

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This is a global variable that persists across all command instances within the same process. Because run, plan, and render all call AddFlagsToSet, only the first command to call it will actually register Consul flags. All subsequent calls silently return early. This also breaks any test that creates more than one command instance, since the flag state is never reset. We should remove the global and use per-flag.Sets or similar if needed.

Comment thread internal/cli/helpers.go

// AddFlags adds all Consul KV configuration flags to the provided flag set.
// This method is called by run, plan, and render commands to register flags.
func (c *ConsulKVConfig) AddFlags(flags *flag.FlagSet) {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This function seems unused, so we can remove it and the import it creates.

Comment thread internal/cli/helpers.go
// Returns nil client if no Consul address is configured (not an error).
// The presence of a Consul address (via CLI flag or CONSUL_HTTP_ADDR env var)
// indicates that Nomad Pack should attempt to create a Consul API client.
func getConsulClient(consulKV *ConsulKVConfig, errorContext *errors.UIErrorContext, ui terminal.UI) (*consulapi.Client, error) {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

errorContextandui` are accepted but never referenced in the function body. Should we be using them, or if not, lets remove them from the function signature.

Comment on lines +18 to +19
wantAddr string
wantToken string

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

It doesn't look like these parameters are ever tested via an assertion. Is this something we want to add, or should we remove them?

Comment on lines +61 to +62
os.Setenv(k, v)
defer os.Unsetenv(k)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

In tests we can use t.Setenv(k, v): https://pkg.go.dev/testing#T.Setenv

@DeekshithaTimmareddy DeekshithaTimmareddy marked this pull request as draft April 29, 2026 13:06
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants