Add consul_key function to integrate concul with hcl2 tempaltes. (#10119)
* Add consul_key function to integrate concul with hcl2 tempaltes. * sidebar nav
This commit is contained in:
parent
4f5e878a17
commit
cc7dbf6092
|
@ -8,6 +8,7 @@ import (
|
|||
"strings"
|
||||
"sync"
|
||||
|
||||
consulapi "github.com/hashicorp/consul/api"
|
||||
vaultapi "github.com/hashicorp/vault/api"
|
||||
)
|
||||
|
||||
|
@ -61,3 +62,27 @@ func Vault(path string, key string) (string, error) {
|
|||
}
|
||||
return "", errors.New("Vault path does not contain the requested key")
|
||||
}
|
||||
|
||||
func Consul(k string) (string, error) {
|
||||
consulConfig := consulapi.DefaultConfig()
|
||||
client, err := consulapi.NewClient(consulConfig)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("error getting consul client: %s", err)
|
||||
}
|
||||
|
||||
q := &consulapi.QueryOptions{}
|
||||
kv, _, err := client.KV().Get(k, q)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("error reading consul key: %s", err)
|
||||
}
|
||||
if kv == nil {
|
||||
return "", fmt.Errorf("key does not exist at the given path: %s", k)
|
||||
}
|
||||
|
||||
value := string(kv.Value)
|
||||
if value == "" {
|
||||
return "", fmt.Errorf("value is empty at path %s", k)
|
||||
}
|
||||
|
||||
return value, nil
|
||||
}
|
||||
|
|
|
@ -0,0 +1,25 @@
|
|||
package function
|
||||
|
||||
import (
|
||||
"github.com/zclconf/go-cty/cty"
|
||||
"github.com/zclconf/go-cty/cty/function"
|
||||
|
||||
commontpl "github.com/hashicorp/packer/common/template"
|
||||
)
|
||||
|
||||
// ConsulFunc constructs a function that retrieves KV secrets from HC vault
|
||||
var ConsulFunc = function.New(&function.Spec{
|
||||
Params: []function.Parameter{
|
||||
{
|
||||
Name: "key",
|
||||
Type: cty.String,
|
||||
},
|
||||
},
|
||||
Type: function.StaticReturnType(cty.String),
|
||||
Impl: func(args []cty.Value, retType cty.Type) (cty.Value, error) {
|
||||
key := args[0].AsString()
|
||||
val, err := commontpl.Consul(key)
|
||||
|
||||
return cty.StringVal(val), err
|
||||
},
|
||||
})
|
|
@ -46,6 +46,7 @@ func Functions(basedir string) map[string]function.Function {
|
|||
"coalescelist": stdlib.CoalesceListFunc,
|
||||
"compact": stdlib.CompactFunc,
|
||||
"concat": stdlib.ConcatFunc,
|
||||
"consul_key": pkrfunction.ConsulFunc,
|
||||
"contains": stdlib.ContainsFunc,
|
||||
"convert": typeexpr.ConvertFunc,
|
||||
"csvdecode": stdlib.CSVDecodeFunc,
|
||||
|
|
|
@ -10,7 +10,6 @@ import (
|
|||
"text/template"
|
||||
"time"
|
||||
|
||||
consulapi "github.com/hashicorp/consul/api"
|
||||
commontpl "github.com/hashicorp/packer/common/template"
|
||||
"github.com/hashicorp/packer/common/uuid"
|
||||
"github.com/hashicorp/packer/helper/common"
|
||||
|
@ -250,34 +249,14 @@ func funcGenPackerVersion(ctx *Context) interface{} {
|
|||
}
|
||||
|
||||
func funcGenConsul(ctx *Context) interface{} {
|
||||
return func(k string) (string, error) {
|
||||
return func(key string) (string, error) {
|
||||
if !ctx.EnableEnv {
|
||||
// The error message doesn't have to be that detailed since
|
||||
// semantic checks should catch this.
|
||||
return "", errors.New("consul_key is not allowed here")
|
||||
}
|
||||
|
||||
consulConfig := consulapi.DefaultConfig()
|
||||
client, err := consulapi.NewClient(consulConfig)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("error getting consul client: %s", err)
|
||||
}
|
||||
|
||||
q := &consulapi.QueryOptions{}
|
||||
kv, _, err := client.KV().Get(k, q)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("error reading consul key: %s", err)
|
||||
}
|
||||
if kv == nil {
|
||||
return "", fmt.Errorf("key does not exist at the given path: %s", k)
|
||||
}
|
||||
|
||||
value := string(kv.Value)
|
||||
if value == "" {
|
||||
return "", fmt.Errorf("value is empty at path %s", k)
|
||||
}
|
||||
|
||||
return value, nil
|
||||
return commontpl.Consul(key)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -33,6 +33,7 @@ export default [
|
|||
category: 'contextual',
|
||||
content: [
|
||||
'vault',
|
||||
'consul',
|
||||
],
|
||||
},
|
||||
{
|
||||
|
|
|
@ -0,0 +1,42 @@
|
|||
---
|
||||
layout: docs
|
||||
page_title: consul - Functions - Configuration Language
|
||||
sidebar_title: consul
|
||||
description: The consul function retrieves secrets from HashiCorp consul KV stores.
|
||||
---
|
||||
|
||||
|
||||
# `consul_key` Function
|
||||
|
||||
[Consul](https://www.consul.io) keys can be used within your template using the
|
||||
`consul_key` function.
|
||||
|
||||
You can either use this function in a locals block or directly inline where you
|
||||
want to use the value.
|
||||
|
||||
```hcl
|
||||
locals {
|
||||
my_version = "${consul_key("myservice/version")}"
|
||||
}
|
||||
|
||||
source "null" "first-example" {
|
||||
communicator = "none"
|
||||
}
|
||||
|
||||
build {
|
||||
name = "my-build-name"
|
||||
sources = ["null.first-example"]
|
||||
|
||||
provisioner "shell-local" {
|
||||
environment_vars = ["TESTVAR=${build.PackerRunUUID}"]
|
||||
inline = ["echo my_version is '${local.my_version}'",
|
||||
"echo version is '${consul_key("myservice/version")}'."]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
This will load the key stored at the path `myservice/version` from consul.
|
||||
|
||||
The configuration for consul (address, tokens, ...) must be specified as
|
||||
environment variables, as specified in the
|
||||
[Documentation](https://www.consul.io/docs/commands#environment-variables).
|
|
@ -46,7 +46,7 @@ stored at the key `foo`, storing it as the local variable `local.foo`.
|
|||
In order for this to work, you must set the environment variables `VAULT_TOKEN`
|
||||
and `VAULT_ADDR` to valid values.
|
||||
|
||||
-> **NOTE:** HCL functions can be used in local variable definitions or inline
|
||||
-> **NOTE:** HCL functions can be used in local variable definitions or inline
|
||||
with a provisioner/post-processor. They cannot be used in global variable definitions.
|
||||
|
||||
The api tool we use allows for more custom configuration of the Vault client via
|
||||
|
|
Loading…
Reference in New Issue