provider/consul: consul_keys data source (#7678)
Previously the consul_keys resource did double-duty as both a reader and writer of values from the Consul key/value store, but that made its interface rather confusing and complex, as well as having all of the other general problems associated with read-only resources. Here we split the functionality such that reading is done with the consul_keys data source while writing is done with the consul_keys resource. The old read behavior of the resource is still supported, but it's no longer documented (except as a deprecation note) and will generate deprecation warnings when used. In future it should be possible to simplify the consul_keys resource by removing all of the read support, but that is deferred for now to give users a chance to gracefully migrate to the new data source.
This commit is contained in:
parent
deba1b63e9
commit
19d0b42911
|
@ -0,0 +1,96 @@
|
|||
package consul
|
||||
|
||||
import (
|
||||
consulapi "github.com/hashicorp/consul/api"
|
||||
"github.com/hashicorp/terraform/helper/schema"
|
||||
)
|
||||
|
||||
func dataSourceConsulKeys() *schema.Resource {
|
||||
return &schema.Resource{
|
||||
Read: dataSourceConsulKeysRead,
|
||||
|
||||
Schema: map[string]*schema.Schema{
|
||||
"datacenter": &schema.Schema{
|
||||
Type: schema.TypeString,
|
||||
Optional: true,
|
||||
Computed: true,
|
||||
ForceNew: true,
|
||||
},
|
||||
|
||||
"token": &schema.Schema{
|
||||
Type: schema.TypeString,
|
||||
Optional: true,
|
||||
},
|
||||
|
||||
"key": &schema.Schema{
|
||||
Type: schema.TypeSet,
|
||||
Optional: true,
|
||||
Elem: &schema.Resource{
|
||||
Schema: map[string]*schema.Schema{
|
||||
"name": &schema.Schema{
|
||||
Type: schema.TypeString,
|
||||
Required: true,
|
||||
},
|
||||
|
||||
"path": &schema.Schema{
|
||||
Type: schema.TypeString,
|
||||
Required: true,
|
||||
},
|
||||
|
||||
"default": &schema.Schema{
|
||||
Type: schema.TypeString,
|
||||
Optional: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
"var": &schema.Schema{
|
||||
Type: schema.TypeMap,
|
||||
Computed: true,
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func dataSourceConsulKeysRead(d *schema.ResourceData, meta interface{}) error {
|
||||
client := meta.(*consulapi.Client)
|
||||
kv := client.KV()
|
||||
token := d.Get("token").(string)
|
||||
dc, err := getDC(d, client)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
keyClient := newKeyClient(kv, dc, token)
|
||||
|
||||
vars := make(map[string]string)
|
||||
|
||||
keys := d.Get("key").(*schema.Set).List()
|
||||
for _, raw := range keys {
|
||||
key, path, sub, err := parseKey(raw)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
value, err := keyClient.Get(path)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
value = attributeValue(sub, value)
|
||||
vars[key] = value
|
||||
}
|
||||
|
||||
if err := d.Set("var", vars); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Store the datacenter on this resource, which can be helpful for reference
|
||||
// in case it was read from the provider
|
||||
d.Set("datacenter", dc)
|
||||
|
||||
d.SetId("-")
|
||||
|
||||
return nil
|
||||
}
|
|
@ -0,0 +1,44 @@
|
|||
package consul
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/hashicorp/terraform/helper/resource"
|
||||
)
|
||||
|
||||
func TestAccDataConsulKeys_basic(t *testing.T) {
|
||||
resource.Test(t, resource.TestCase{
|
||||
PreCheck: func() { testAccPreCheck(t) },
|
||||
Providers: testAccProviders,
|
||||
Steps: []resource.TestStep{
|
||||
resource.TestStep{
|
||||
Config: testAccDataConsulKeysConfig,
|
||||
Check: resource.ComposeTestCheckFunc(
|
||||
testAccCheckConsulKeysValue("data.consul_keys.read", "read", "written"),
|
||||
),
|
||||
},
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
const testAccDataConsulKeysConfig = `
|
||||
resource "consul_keys" "write" {
|
||||
datacenter = "dc1"
|
||||
|
||||
key {
|
||||
path = "test/data_source"
|
||||
value = "written"
|
||||
}
|
||||
}
|
||||
|
||||
data "consul_keys" "read" {
|
||||
# Create a dependency on the resource so we're sure to
|
||||
# have the value in place before we try to read it.
|
||||
datacenter = "${consul_keys.write.datacenter}"
|
||||
|
||||
key {
|
||||
path = "test/data_source"
|
||||
name = "read"
|
||||
}
|
||||
}
|
||||
`
|
|
@ -37,8 +37,9 @@ func resourceConsulKeys() *schema.Resource {
|
|||
Elem: &schema.Resource{
|
||||
Schema: map[string]*schema.Schema{
|
||||
"name": &schema.Schema{
|
||||
Type: schema.TypeString,
|
||||
Required: true,
|
||||
Type: schema.TypeString,
|
||||
Optional: true,
|
||||
Deprecated: "Using consul_keys resource to *read* is deprecated; please use consul_keys data source instead",
|
||||
},
|
||||
|
||||
"path": &schema.Schema{
|
||||
|
@ -220,7 +221,12 @@ func resourceConsulKeysRead(d *schema.ResourceData, meta interface{}) error {
|
|||
}
|
||||
|
||||
value = attributeValue(sub, value)
|
||||
vars[key] = value
|
||||
if key != "" {
|
||||
// If key is set then we'll update vars, for backward-compatibilty
|
||||
// with the pre-0.7 capability to read from Consul with this
|
||||
// resource.
|
||||
vars[key] = value
|
||||
}
|
||||
|
||||
// If there is already a "value" attribute present for this key
|
||||
// then it was created as a "write" block. We need to update the
|
||||
|
@ -290,10 +296,7 @@ func parseKey(raw interface{}) (string, string, map[string]interface{}, error) {
|
|||
return "", "", nil, fmt.Errorf("Failed to unroll: %#v", raw)
|
||||
}
|
||||
|
||||
key, ok := sub["name"].(string)
|
||||
if !ok {
|
||||
return "", "", nil, fmt.Errorf("Failed to expand key '%#v'", sub)
|
||||
}
|
||||
key := sub["name"].(string)
|
||||
|
||||
path, ok := sub["path"].(string)
|
||||
if !ok {
|
||||
|
|
|
@ -28,6 +28,10 @@ func Provider() terraform.ResourceProvider {
|
|||
},
|
||||
},
|
||||
|
||||
DataSourcesMap: map[string]*schema.Resource{
|
||||
"consul_keys": dataSourceConsulKeys(),
|
||||
},
|
||||
|
||||
ResourcesMap: map[string]*schema.Resource{
|
||||
"consul_keys": resourceConsulKeys(),
|
||||
"consul_key_prefix": resourceConsulKeyPrefix(),
|
||||
|
|
|
@ -0,0 +1,67 @@
|
|||
---
|
||||
layout: "consul"
|
||||
page_title: "Consul: consul_keys"
|
||||
sidebar_current: "docs-consul-data-source-keys"
|
||||
description: |-
|
||||
Reads values from the Consul key/value store.
|
||||
---
|
||||
|
||||
# consul\_keys
|
||||
|
||||
`consul_keys` reads values from the Consul key/value store.
|
||||
This is a powerful way dynamically set values in templates.
|
||||
|
||||
## Example Usage
|
||||
|
||||
```
|
||||
data "consul_keys" "app" {
|
||||
datacenter = "nyc1"
|
||||
token = "abcd"
|
||||
|
||||
# Read the launch AMI from Consul
|
||||
key {
|
||||
name = "ami"
|
||||
path = "service/app/launch_ami"
|
||||
default = "ami-1234"
|
||||
}
|
||||
}
|
||||
|
||||
# Start our instance with the dynamic ami value
|
||||
resource "aws_instance" "app" {
|
||||
ami = "${data.consul_keys.app.var.ami}"
|
||||
...
|
||||
}
|
||||
```
|
||||
|
||||
## Argument Reference
|
||||
|
||||
The following arguments are supported:
|
||||
|
||||
* `datacenter` - (Optional) The datacenter to use. This overrides the
|
||||
datacenter in the provider setup and the agent's default datacenter.
|
||||
|
||||
* `token` - (Optional) The ACL token to use. This overrides the
|
||||
token that the agent provides by default.
|
||||
|
||||
* `key` - (Required) Specifies a key in Consul to be read or written.
|
||||
Supported values documented below.
|
||||
|
||||
The `key` block supports the following:
|
||||
|
||||
* `name` - (Required) This is the name of the key. This value of the
|
||||
key is exposed as `var.<name>`. This is not the path of the key
|
||||
in Consul.
|
||||
|
||||
* `path` - (Required) This is the path in Consul that should be read
|
||||
or written to.
|
||||
|
||||
* `default` - (Optional) This is the default value to set for `var.<name>`
|
||||
if the key does not exist in Consul. Defaults to the empty string.
|
||||
|
||||
## Attributes Reference
|
||||
|
||||
The following attributes are exported:
|
||||
|
||||
* `datacenter` - The datacenter the keys are being read from to.
|
||||
* `var.<name>` - For each name given, the corresponding attribute
|
||||
has the value of the key.
|
|
@ -3,15 +3,13 @@ layout: "consul"
|
|||
page_title: "Consul: consul_keys"
|
||||
sidebar_current: "docs-consul-resource-keys"
|
||||
description: |-
|
||||
Provides access to Key/Value data in Consul. This can be used to both read keys from Consul, but also to set the value of keys in Consul. This is a powerful way dynamically set values in templates, and to expose infrastructure details to clients.
|
||||
Writes values into the Consul key/value store.
|
||||
---
|
||||
|
||||
# consul\_keys
|
||||
|
||||
Provides access to Key/Value data in Consul. This can be used
|
||||
to both read keys from Consul, but also to set the value of keys
|
||||
in Consul. This is a powerful way dynamically set values in templates,
|
||||
and to expose infrastructure details to clients.
|
||||
`consul_keys` writes sets of individual values into Consul.
|
||||
This is a powerful way to expose infrastructure details to clients.
|
||||
|
||||
This resource manages individual keys, and thus it can create, update and
|
||||
delete the keys explicitly given. Howver, It is not able to detect and remove
|
||||
|
@ -27,13 +25,6 @@ resource "consul_keys" "app" {
|
|||
datacenter = "nyc1"
|
||||
token = "abcd"
|
||||
|
||||
# Read the launch AMI from Consul
|
||||
key {
|
||||
name = "ami"
|
||||
path = "service/app/launch_ami"
|
||||
default = "ami-1234"
|
||||
}
|
||||
|
||||
# Set the CNAME of our load balancer as a key
|
||||
key {
|
||||
name = "elb_cname"
|
||||
|
@ -41,12 +32,6 @@ resource "consul_keys" "app" {
|
|||
value = "${aws_elb.app.dns_name}"
|
||||
}
|
||||
}
|
||||
|
||||
# Start our instance with the dynamic ami value
|
||||
resource "aws_instance" "app" {
|
||||
ami = "${consul_keys.app.var.ami}"
|
||||
...
|
||||
}
|
||||
```
|
||||
|
||||
## Argument Reference
|
||||
|
@ -59,33 +44,31 @@ The following arguments are supported:
|
|||
* `token` - (Optional) The ACL token to use. This overrides the
|
||||
token that the agent provides by default.
|
||||
|
||||
* `key` - (Required) Specifies a key in Consul to be read or written.
|
||||
* `key` - (Required) Specifies a key in Consul to be written.
|
||||
Supported values documented below.
|
||||
|
||||
The `key` block supports the following:
|
||||
|
||||
* `name` - (Required) This is the name of the key. This value of the
|
||||
key is exposed as `var.<name>`. This is not the path of the key
|
||||
in Consul.
|
||||
* `path` - (Required) This is the path in Consul that should be written to.
|
||||
|
||||
* `path` - (Required) This is the path in Consul that should be read
|
||||
or written to.
|
||||
|
||||
* `default` - (Optional) This is the default value to set for `var.<name>`
|
||||
if the key does not exist in Consul. Defaults to the empty string.
|
||||
|
||||
* `value` - (Optional) If set, the key will be set to this value.
|
||||
This allows a key to be written to.
|
||||
* `value` - (Required) The value to write to the given path.
|
||||
|
||||
* `delete` - (Optional) If true, then the key will be deleted when
|
||||
either its configuration block is removed from the configuration or
|
||||
the entire resource is destroyed. Otherwise, it will be left in Consul.
|
||||
Defaults to false.
|
||||
|
||||
### Deprecated `key` arguments
|
||||
|
||||
Prior to Terraform 0.7 this resource was used both to read *and* write the
|
||||
Consul key/value store. The read functionality has moved to the `consul_keys`
|
||||
*data source*, whose documentation can be found via the navigation.
|
||||
|
||||
The pre-0.7 interface for reading is still supported for backward compatibilty,
|
||||
but will be removed in a future version of Terraform.
|
||||
|
||||
## Attributes Reference
|
||||
|
||||
The following attributes are exported:
|
||||
|
||||
* `datacenter` - The datacenter the keys are being read/written to.
|
||||
* `var.<name>` - For each name given, the corresponding attribute
|
||||
has the value of the key.
|
||||
* `datacenter` - The datacenter the keys are being written to.
|
||||
|
|
|
@ -10,6 +10,15 @@
|
|||
<a href="/docs/providers/consul/index.html">Consul Provider</a>
|
||||
</li>
|
||||
|
||||
<li<%= sidebar_current(/^docs-consul-data-source/) %>>
|
||||
<a href="#">Data Sources</a>
|
||||
<ul class="nav nav-visible">
|
||||
<li<%= sidebar_current("docs-consul-data-source-keys") %>>
|
||||
<a href="/docs/providers/consul/d/keys.html">consul_keys</a>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
|
||||
<li<%= sidebar_current(/^docs-consul-resource/) %>>
|
||||
<a href="#">Resources</a>
|
||||
<ul class="nav nav-visible">
|
||||
|
|
Loading…
Reference in New Issue