Skip to content

Commit

Permalink
Merge pull request #167 from terraform-providers/f-tag-category-data-…
Browse files Browse the repository at this point in the history
…source

New data source: vsphere_tag_category
  • Loading branch information
vancluever authored Sep 19, 2017
2 parents 077dec9 + ffc95d8 commit 08e1ba5
Show file tree
Hide file tree
Showing 8 changed files with 256 additions and 41 deletions.
47 changes: 47 additions & 0 deletions vsphere/data_source_vsphere_tag_category.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
package vsphere

import "github.com/hashicorp/terraform/helper/schema"

func dataSourceVSphereTagCategory() *schema.Resource {
return &schema.Resource{
Read: dataSourceVSphereTagCategoryRead,
Schema: map[string]*schema.Schema{
"name": {
Type: schema.TypeString,
Description: "The display name of the category.",
Required: true,
},
"description": {
Type: schema.TypeString,
Computed: true,
Description: "The description of the category.",
},
"cardinality": {
Type: schema.TypeString,
Computed: true,
Description: "The associated cardinality of the category. Can be one of SINGLE (object can only be assigned one tag in this category) or MULTIPLE (object can be assigned multiple tags in this category).",
},
"associable_types": {
Type: schema.TypeSet,
Computed: true,
Description: "Object types to which this category's tags can be attached.",
Elem: &schema.Schema{Type: schema.TypeString},
},
},
}
}

func dataSourceVSphereTagCategoryRead(d *schema.ResourceData, meta interface{}) error {
client, err := meta.(*VSphereClient).TagsClient()
if err != nil {
return err
}

id, err := tagCategoryByName(client, d.Get("name").(string))
if err != nil {
return err
}

d.SetId(id)
return resourceVSphereTagCategoryRead(d, meta)
}
115 changes: 115 additions & 0 deletions vsphere/data_source_vsphere_tag_category_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
package vsphere

import (
"fmt"
"testing"

"github.com/hashicorp/terraform/helper/resource"
)

func TestAccDataSourceVSphereTagCategory(t *testing.T) {
var tp *testing.T
testAccDataSourceVSphereTagCategoryCases := []struct {
name string
testCase resource.TestCase
}{
{
"basic",
resource.TestCase{
PreCheck: func() {
testAccPreCheck(tp)
},
Providers: testAccProviders,
Steps: []resource.TestStep{
{
Config: testAccDataSourceVSphereTagCategoryConfig(),
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttr(
"data.vsphere_tag_category.terraform-test-category-data",
"name",
testAccDataSourceVSphereTagCategoryConfigName,
),
resource.TestCheckResourceAttr(
"data.vsphere_tag_category.terraform-test-category-data",
"description",
testAccDataSourceVSphereTagCategoryConfigDescription,
),
resource.TestCheckResourceAttr(
"data.vsphere_tag_category.terraform-test-category-data",
"cardinality",
testAccDataSourceVSphereTagCategoryConfigCardinality,
),
resource.TestCheckResourceAttr(
"data.vsphere_tag_category.terraform-test-category-data",
"associable_types.#",
"1",
),
resource.TestCheckResourceAttr(
"data.vsphere_tag_category.terraform-test-category-data",
"associable_types.3125094965",
testAccDataSourceVSphereTagCategoryConfigAssociableType,
),
resource.TestCheckResourceAttrPair(
"data.vsphere_tag_category.terraform-test-category-data", "id",
"vsphere_tag_category.terraform-test-category", "id",
),
),
},
},
},
},
}

for _, tc := range testAccDataSourceVSphereTagCategoryCases {
t.Run(tc.name, func(t *testing.T) {
tp = t
resource.Test(t, tc.testCase)
})
}
}

const testAccDataSourceVSphereTagCategoryConfigName = "terraform-test-category"
const testAccDataSourceVSphereTagCategoryConfigDescription = "Managed by Terraform"
const testAccDataSourceVSphereTagCategoryConfigCardinality = vSphereTagCategoryCardinalitySingle
const testAccDataSourceVSphereTagCategoryConfigAssociableType = vSphereTagCategoryAssociableTypeVirtualMachine

func testAccDataSourceVSphereTagCategoryConfig() string {
return fmt.Sprintf(`
variable "tag_category_name" {
default = "%s"
}
variable "tag_category_description" {
default = "%s"
}
variable "tag_category_cardinality" {
default = "%s"
}
variable "tag_category_associable_types" {
default = [
"%s",
]
}
resource "vsphere_tag_category" "terraform-test-category" {
name = "${var.tag_category_name}"
description = "${var.tag_category_description}"
cardinality = "${var.tag_category_cardinality}"
associable_types = [
"${var.tag_category_associable_types}",
]
}
data "vsphere_tag_category" "terraform-test-category-data" {
name = "${vsphere_tag_category.terraform-test-category.name}"
}
`,
testAccDataSourceVSphereTagCategoryConfigName,
testAccDataSourceVSphereTagCategoryConfigDescription,
testAccDataSourceVSphereTagCategoryConfigCardinality,
testAccDataSourceVSphereTagCategoryConfigAssociableType,
)
}
7 changes: 4 additions & 3 deletions vsphere/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -84,9 +84,10 @@ func Provider() terraform.ResourceProvider {
},

DataSourcesMap: map[string]*schema.Resource{
"vsphere_datacenter": dataSourceVSphereDatacenter(),
"vsphere_host": dataSourceVSphereHost(),
"vsphere_vmfs_disks": dataSourceVSphereVmfsDisks(),
"vsphere_datacenter": dataSourceVSphereDatacenter(),
"vsphere_host": dataSourceVSphereHost(),
"vsphere_tag_category": dataSourceVSphereTagCategory(),
"vsphere_vmfs_disks": dataSourceVSphereVmfsDisks(),
},

ConfigureFunc: providerConfigure,
Expand Down
37 changes: 3 additions & 34 deletions vsphere/resource_vsphere_tag_category.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,20 +10,6 @@ import (
"github.com/vmware/vic/pkg/vsphere/tags"
)

// resourceVSphereTagCategoryImportErrMultiple is an error message format for a
// tag category import that returned multiple results. This is a bug and needs
// to be reported so we can adjust the API.
const resourceVSphereTagCategoryImportErrMultiple = `
Category name %q returned multiple results!
This is a bug - please report it at:
https://github.com/terraform-providers/terraform-provider-vsphere/issues
This version of the provider requires unique category names. To work around
this issue, please rename your category to a name unique within your vCenter
system.
`

// A list of valid types for cardinality and associable types are below. The
// latter is more significant, even though they are not used in the resource
// itself, to ensure all associable types are properly documented so we can
Expand Down Expand Up @@ -225,33 +211,16 @@ func resourceVSphereTagCategoryDelete(d *schema.ResourceData, meta interface{})
}

func resourceVSphereTagCategoryImport(d *schema.ResourceData, meta interface{}) ([]*schema.ResourceData, error) {
// Although GetCategoriesByName does not seem to think that tag categories
// are unique, empirical observation via the console and API show that they
// are. Hence we can just import by the tag name. If for some reason the
// returned results includes more than one ID, we give an error.
client, err := meta.(*VSphereClient).TagsClient()
if err != nil {
return nil, err
}

name := d.Id()

ctx, cancel := context.WithTimeout(context.Background(), defaultAPITimeout)
defer cancel()
cats, err := client.GetCategoriesByName(ctx, name)
id, err := tagCategoryByName(client, d.Id())
if err != nil {
return nil, fmt.Errorf("could not get category for name %q: %s", name, err)
}

if len(cats) < 1 {
return nil, fmt.Errorf("category name %q not found", name)
}
if len(cats) > 1 {
// This should not happen but guarding just in case it does. This is a bug
// and needs to be reported.
return nil, fmt.Errorf(resourceVSphereTagCategoryImportErrMultiple, name)
return nil, err
}

d.SetId(cats[0].ID)
d.SetId(id)
return []*schema.ResourceData{d}, nil
}
42 changes: 42 additions & 0 deletions vsphere/tags_helper.go
Original file line number Diff line number Diff line change
@@ -1,9 +1,26 @@
package vsphere

import (
"context"
"fmt"

"github.com/vmware/govmomi"
"github.com/vmware/vic/pkg/vsphere/tags"
)

// vSphereTagCategorySearchErrMultiple is an error message format for a tag
// category search that returned multiple results. This is a bug and needs to
// be reported so we can adjust the API.
const vSphereTagCategorySearchErrMultiple = `
Category name %q returned multiple results!
This is a bug - please report it at:
https://github.com/terraform-providers/terraform-provider-vsphere/issues
This version of the provider requires unique category names. To work around
this issue, please use a category name unique within your vCenter system.
`

// tagsMinVersion is the minimum vSphere version required for tags.
var tagsMinVersion = vSphereVersion{
product: "VMware vCenter Server",
Expand All @@ -24,3 +41,28 @@ func isEligibleTagEndpoint(client *govmomi.Client) bool {
}
return true
}

// tagCategoryByName locates a tag category by name. It's used by the
// vsphere_tag_category data source, and the resource importer.
func tagCategoryByName(client *tags.RestClient, name string) (string, error) {
ctx, cancel := context.WithTimeout(context.Background(), defaultAPITimeout)
defer cancel()
cats, err := client.GetCategoriesByName(ctx, name)
if err != nil {
return "", fmt.Errorf("could not get category for name %q: %s", name, err)
}

if len(cats) < 1 {
return "", fmt.Errorf("category name %q not found", name)
}
if len(cats) > 1 {
// Although GetCategoriesByName does not seem to think that tag categories
// are unique, empirical observation via the console and API show that they
// are. If for some reason the returned results includes more than one ID,
// we give an error, indicating that this is a bug and the user should
// submit an issue.
return "", fmt.Errorf(vSphereTagCategorySearchErrMultiple, name)
}

return cats[0].ID, nil
}
40 changes: 40 additions & 0 deletions website/docs/d/tag_category.html.markdown
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
---
layout: "vsphere"
page_title: "VMware vSphere: vsphere_tag_category"
sidebar_current: "docs-vsphere-data-source-tag-category"
description: |-
Provides a vSphere tag category data source. This can be used to reference tag categories not managed in Terraform.
---

# vsphere\_tag\_category

The `vsphere_tag_category` data source can be used to reference tag categories
that are not managed by Terraform. Its attributes are exactly the same as the
[`vsphere_tag_category` resource][resource-tag-category], and, like importing,
the data source takes a name to search on. The `id` and other attributes are
then populated with the data found by the search.

[resource-tag-category]: /docs/providers/vsphere/r/tag_category.html

~> **NOTE:** Tagging support is unsupported on direct ESXi connections and
requires vCenter 6.0 or higher.

## Example Usage

```hcl
data "vsphere_tag_category" "category" {
name = "terraform-test-category"
}
```

## Argument Reference

The following arguments are supported:

* `name` - (String, required) The name of the tag category.

## Attribute Reference

In addition to the `id` being exported, all of the fields that are available in
the [`vsphere_tag_category` resource][resource-tag-category] are also
populated. See that page for further details.
6 changes: 2 additions & 4 deletions website/docs/r/tag_category.html.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,6 @@ information about tag categories specifically, click
~> **NOTE:** Tagging support is unsupported on direct ESXi connections and
requires vCenter 6.0 or higher.

[resource-vmfs-datastore]: /docs/providers/vsphere/r/vmfs_datastore.html

## Example Usage

This example creates a tag category named `terraform-test-category`, with
Expand All @@ -48,8 +46,8 @@ resource "vsphere_tag_category" "category" {

The following arguments are supported:

* `name` - (String, required) The name of the tag.
* `description` - (String, optional) A description for the tag.
* `name` - (String, required) The name of the category.
* `description` - (String, optional) A description for the category.
* `cardinality` - (String, required, forces new resource) The number of tags
that can be assigned from this category to a single object at once. Can be
one of `SINGLE` (object can only be assigned one tag in this category), to
Expand Down
3 changes: 3 additions & 0 deletions website/vsphere.erb
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,9 @@
<li<%= sidebar_current("docs-vsphere-data-source-host") %>>
<a href="/docs/providers/vsphere/d/host.html">vsphere_host</a>
</li>
<li<%= sidebar_current("docs-vsphere-data-source-tag-category") %>>
<a href="/docs/providers/vsphere/d/tag_category.html">vsphere_tag_category</a>
</li>
<li<%= sidebar_current("docs-vsphere-data-source-vmfs-disks") %>>
<a href="/docs/providers/vsphere/d/vmfs_disks.html">vsphere_vmfs_disks</a>
</li>
Expand Down

0 comments on commit 08e1ba5

Please sign in to comment.