Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

New data source: vsphere_tag_category #167

Merged
merged 2 commits into from
Sep 19, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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.
Copy link
Member

Choose a reason for hiding this comment

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

Thoughts about linking that page?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It is linked - just above as it's the same link 🙂

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