diff --git a/builtin/providers/consul/data_source_consul_catalog_services.go b/builtin/providers/consul/data_source_consul_catalog_services.go index dd4e7bedc5..ad7535a09a 100644 --- a/builtin/providers/consul/data_source_consul_catalog_services.go +++ b/builtin/providers/consul/data_source_consul_catalog_services.go @@ -11,10 +11,13 @@ import ( ) const ( - catalogServicesDatacenter = "datacenter" - catalogServicesNames = "names" - + // Datasource predicates catalogServicesServiceName = "name" + + // Out parameters + catalogServicesDatacenter = "datacenter" + catalogServicesNames = "names" + catalogServicesServices = "services" catalogServicesServiceTags = "tags" ) @@ -34,17 +37,19 @@ func dataSourceConsulCatalogServices() *schema.Resource { // Out parameters catalogServicesNames: &schema.Schema{ + Type: schema.TypeList, + Computed: true, + Elem: &schema.Schema{Type: schema.TypeString}, + }, + catalogServicesServices: &schema.Schema{ Computed: true, Type: schema.TypeMap, Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ catalogServiceServiceTags: &schema.Schema{ - // FIXME(sean@): Tags is currently a space separated list of tags. - // The ideal structure should be map[string][]string instead. - // When this is supported in the future this should be changed to - // be a TypeList instead. - Type: schema.TypeString, + Type: schema.TypeList, Computed: true, + Elem: &schema.Schema{Type: schema.TypeString}, }, }, }, @@ -67,7 +72,7 @@ func dataSourceConsulCatalogServicesRead(d *schema.ResourceData, meta interface{ return err } - m := make(map[string]interface{}, len(services)) + catalogServices := make(map[string]interface{}, len(services)) for name, tags := range services { tagList := make([]string, 0, len(tags)) for _, tag := range tags { @@ -75,16 +80,25 @@ func dataSourceConsulCatalogServicesRead(d *schema.ResourceData, meta interface{ } sort.Strings(tagList) - m[name] = strings.Join(tagList, " ") + catalogServices[name] = strings.Join(tagList, " ") + } + + serviceNames := make([]interface{}, 0, len(services)) + for k := range catalogServices { + serviceNames = append(serviceNames, k) } const idKeyFmt = "catalog-services-%s" d.SetId(fmt.Sprintf(idKeyFmt, queryOpts.Datacenter)) d.Set(catalogServicesDatacenter, queryOpts.Datacenter) - if err := d.Set(catalogServicesNames, m); err != nil { + if err := d.Set(catalogServicesServices, catalogServices); err != nil { return errwrap.Wrapf("Unable to store services: {{err}}", err) } + if err := d.Set(catalogServicesNames, serviceNames); err != nil { + return errwrap.Wrapf("Unable to store service names: {{err}}", err) + } + return nil } diff --git a/builtin/providers/consul/data_source_consul_catalog_services_test.go b/builtin/providers/consul/data_source_consul_catalog_services_test.go index 661a9b96b1..1087073f7d 100644 --- a/builtin/providers/consul/data_source_consul_catalog_services_test.go +++ b/builtin/providers/consul/data_source_consul_catalog_services_test.go @@ -15,8 +15,8 @@ func TestAccDataConsulCatalogServices_basic(t *testing.T) { Config: testAccDataConsulCatalogServicesConfig, Check: resource.ComposeTestCheckFunc( testAccCheckDataSourceValue("data.consul_catalog_services.read", "datacenter", "dc1"), - testAccCheckDataSourceValue("data.consul_catalog_services.read", "names.%", "1"), - testAccCheckDataSourceValue("data.consul_catalog_services.read", "names.consul", ""), + testAccCheckDataSourceValue("data.consul_catalog_services.read", "services.%", "1"), + testAccCheckDataSourceValue("data.consul_catalog_services.read", "services.consul", ""), ), }, }, diff --git a/website/source/docs/providers/consul/d/services.html.markdown b/website/source/docs/providers/consul/d/services.html.markdown new file mode 100644 index 0000000000..f8fe6ee474 --- /dev/null +++ b/website/source/docs/providers/consul/d/services.html.markdown @@ -0,0 +1,80 @@ +--- +layout: "consul" +page_title: "Consul: consul_catalog_services" +sidebar_current: "docs-consul-data-source-catalog-services" +description: |- + Provides a list of services in a given Consul datacenter. +--- + +# consul\_catalog\_services + +The `consul_catalog_services` data source returns a list of Consul services that +have been registered with the Consul cluster in a given datacenter. By +specifying a different datacenter in the `query_options` it is possible to +retrieve a list of services from a different WAN-attached Consul datacenter. + +This data source is different from the `consul_catalog_service` (singular) data +source, which provides a detailed response about a specific Consul service. + +## Example Usage + +``` +data "consul_catalog_services" "read-dc1" { + query_options { + # Optional parameter + datacenter = "dc1" + } +} + +# Set the description to a whitespace delimited list of the services +resource "example_resource" "app" { + description = "${join(" ", data.consul_catalog_services.names)}" + ... +} +``` + +## Argument Reference + +The following arguments are supported: + +* `datacenter` - (Optional) The Consul datacenter to query. Defaults to the + same value found in `query_options` parameter specified below, or if that is + empty, the `datacenter` value found in the Consul agent that this provider is + configured to talk to. + +* `query_options` - (Optional) See below. + +The `query_options` block supports the following: + +* `allow_stale` - (Optional) When `true`, the default, allow responses from + Consul servers that are followers. + +* `require_consistent` - (Optional) When `true` force the client to perform a + read on at least quorum servers and verify the result is the same. Defaults + to `false`. + +* `token` - (Optional) Specify the Consul ACL token to use when performing the + request. This defaults to the same API token configured by the `consul` + provider but may be overriden if necessary. + +* `wait_index` - (Optional) Index number used to enable blocking quereis. + +* `wait_time` - (Optional) Max time the client should wait for a blocking query + to return. + +## Attributes Reference + +The following attributes are exported: + +* `datacenter` - The datacenter the keys are being read from to. +* `names` - A list of the Consul services found. This will always contain the + list of services found. +* `services.` - For each name given, the corresponding attribute is a + Terraform map of services and their tags. The value is an alphanumerically + sorted, whitespace delimited set of tags associated with the service. As + shown in the example above, to create a list of the available servies, wrap + the `names` attribute in a call to `keys()`. +* `tags` - A map of the tags found for each service. If more than one service + shares the same tag, unique service names will be joined by whitespace (this + is the inverse of `services` and can be used to lookup the services that match + a single tag). diff --git a/website/source/layouts/consul.erb b/website/source/layouts/consul.erb index df831b0587..32e0efa1d1 100644 --- a/website/source/layouts/consul.erb +++ b/website/source/layouts/consul.erb @@ -13,10 +13,13 @@ > Data Sources + > + consul_catalog_services + + > + consul_keys + + >