Skip to content

Commit c79b405

Browse files
feat: create resource and data source for host configuration profiles (#2588)
Signed-off-by: Stoyan Zhelyazkov <stoyan.zhelyazkov@broadcom.com> Co-authored-by: Ryan Johnson <ryan.johnson@broadcom.com>
1 parent 0e172ff commit c79b405

8 files changed

+612
-0
lines changed
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
---
2+
subcategory: "Host and Cluster Management"
3+
page_title: "VMware vSphere: vsphere_configuration_profile"
4+
sidebar_current: "docs-vsphere-data-source-config-profile"
5+
description: |-
6+
Provides a vSphere cluster configuration profile data source.
7+
---
8+
9+
# vsphere_configuration_profile
10+
11+
The `vsphere_configuration_profile` data source can be used to export the configuration and schema
12+
of a cluster that is already managed via configuration profiles.
13+
14+
## Example Usage
15+
16+
```hcl
17+
data "vsphere_datacenter" "datacenter" {
18+
name = "dc-01"
19+
}
20+
21+
data "vsphere_compute_cluster" "compute_cluster" {
22+
name = "cluster-01"
23+
datacenter_id = data.vsphere_datacenter.datacenter.id
24+
}
25+
26+
data "vsphere_configuration_profile" "profile" {
27+
cluster_id = data.vsphere_compute_cluster.compute_cluster.id
28+
}
29+
```
30+
31+
## Argument Reference
32+
33+
The following arguments are supported:
34+
35+
* `cluster_id` - (Required) The identifier of the compute cluster.
36+
37+
## Attribute Reference
38+
39+
The following attributes are exported:
40+
41+
* `id` - A custom identifier for the profile. The value for this attribute is constructed using the `cluster_id` in the following format - `configuration_profile_${cluster_id}`.
42+
* `schema`- The JSON schema for the profile.
43+
* `configuration` - The current configuration which is active on the cluster.
Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
---
2+
subcategory: "Host and Cluster Management"
3+
page_title: "VMware vSphere: vsphere_configuration_profile"
4+
sidebar_current: "docs-vsphere-resource-config-profile"
5+
description: |-
6+
Provides a vSphere cluster configuration profile resource.
7+
---
8+
9+
# vsphere_configuration_profile
10+
11+
The `vsphere_configuration_profile` resource can be used to configure profile-based host management on a vSphere compute cluster.
12+
The source for the configuration can either be a ESXi host that is part of the compute cluster or a JSON file, but not both at the same time.
13+
14+
It is allowed to switch from one type of configuration source to the other at any time.
15+
16+
Deleting a `vsphere_configuration_profile` resource has no effect on the compute cluster. Once management via configuration
17+
profiles is turned ot it is not possible to disable it.
18+
19+
~> **NOTE:** This resource requires a vCenter 8 or higher and will not work on
20+
direct ESXi connections.
21+
22+
## Example Usage
23+
24+
### Creating a profile using an ESXi host as a reference
25+
26+
The following example sets up a configuration profile on a compute cluster using one of its hosts as a reference
27+
and then propagates that configuration to two additional clusters.
28+
29+
Note that this example assumes that the hosts across all three clusters are compatible with the source configuration.
30+
This includes but is not limited to their ESXi versions and hardware capabilities.
31+
32+
```hcl
33+
data "vsphere_datacenter" "datacenter" {
34+
name = "dc-01"
35+
}
36+
37+
data "vsphere_compute_cluster" "cluster1" {
38+
name = "cluster-01"
39+
datacenter_id = data.vsphere_datacenter.datacenter.id
40+
}
41+
42+
data "vsphere_compute_cluster" "cluster2" {
43+
name = "cluster-02"
44+
datacenter_id = data.vsphere_datacenter.datacenter.id
45+
}
46+
47+
data "vsphere_compute_cluster" "cluster3" {
48+
name = "cluster-03"
49+
datacenter_id = data.vsphere_datacenter.datacenter.id
50+
}
51+
52+
# This host is assumed to be part of "cluster-01"
53+
data "vsphere_host" "host" {
54+
name = "esxi-01.example.com"
55+
datacenter_id = data.vsphere_datacenter.datacenter.id
56+
}
57+
58+
# Configure a profile on "cluster-01" using one of its hosts as a reference
59+
resource "vsphere_configuration_profile" "profile1" {
60+
cluster_id = data.vsphere_compute_cluster.cluster1.id
61+
reference_host_id = data.vsphere_host.host.id
62+
}
63+
64+
# Copy the configuration of "cluster-01" onto "cluster-02"
65+
resource "vsphere_configuration_profile" "profile2" {
66+
cluster_id = data.vsphere_compute_cluster.cluster2.id
67+
configuration = vsphere_configuration_profile.profile1.configuration
68+
}
69+
70+
# Copy the configuration of "cluster-01" onto "cluster-03"
71+
resource "vsphere_configuration_profile" "profile3" {
72+
cluster_id = data.vsphere_compute_cluster.cluster3.id
73+
configuration = vsphere_configuration_profile.profile1.configuration
74+
}
75+
```
76+
77+
### Creating a profile using a configuration file
78+
79+
This example sets up a configuration profile on a cluster by reading a configuration from a JSON
80+
file on the local filesystem. Reading files is natively supported by Terraform.
81+
82+
```hcl
83+
data "vsphere_datacenter" "datacenter" {
84+
name = "dc-01"
85+
}
86+
87+
data "vsphere_compute_cluster" "cluster1" {
88+
name = "cluster-01"
89+
datacenter_id = data.vsphere_datacenter.datacenter.id
90+
}
91+
92+
resource "vsphere_configuration_profile" "profile1" {
93+
cluster_id = data.vsphere_compute_cluster.cluster1.id
94+
configuration = file("/path/to/cluster_config_1.json")
95+
}
96+
```
97+
98+
## Argument Reference
99+
100+
The following arguments are supported:
101+
102+
* `cluster_id` - (Required) The identifier of the cluster.
103+
* `reference_host_id` - (Optional) The identifier of the host to use as a configuration source.
104+
The host needs to be a member of the cluster identified by `cluster_id`. This argument can only be specified if
105+
`configuration` is not set.
106+
* `configuration` - (Optional) The configuration JSON provided as a plain string. This argument can only be specified if `reference_host_id` is not set.
107+
108+
## Attribute Reference
109+
110+
The following attributes are exported:
111+
112+
* `id` - A custom identifier for the profile. The value for this attribute is constructed using the `cluster_id` in the following format - `configuration_profile_${cluster_id}`.
113+
* `schema`- The JSON schema for the profile.
114+
* `configuration` - The current configuration which is active on the cluster.
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
// © Broadcom. All Rights Reserved.
2+
// The term "Broadcom" refers to Broadcom Inc. and/or its subsidiaries.
3+
// SPDX-License-Identifier: MPL-2.0
4+
5+
package vsphere
6+
7+
import (
8+
"context"
9+
10+
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
11+
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
12+
"github.com/vmware/terraform-provider-vsphere/vsphere/internal/helper/configprofile"
13+
)
14+
15+
func dataSourceVSphereConfigurationProfile() *schema.Resource {
16+
return &schema.Resource{
17+
ReadContext: dataSourceVSphereConfigurationProfileRead,
18+
Schema: map[string]*schema.Schema{
19+
"configuration": {
20+
Type: schema.TypeString,
21+
Computed: true,
22+
Description: "The configuration JSON.",
23+
},
24+
"schema": {
25+
Type: schema.TypeString,
26+
Computed: true,
27+
Description: "The configuration schema.",
28+
},
29+
"cluster_id": {
30+
Type: schema.TypeString,
31+
Required: true,
32+
Description: "The identifier of the cluster.",
33+
},
34+
},
35+
}
36+
}
37+
38+
func dataSourceVSphereConfigurationProfileRead(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
39+
client := meta.(*Client).restClient
40+
return configprofile.ReadConfigProfile(ctx, client, d)
41+
}
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
// © Broadcom. All Rights Reserved.
2+
// The term "Broadcom" refers to Broadcom Inc. and/or its subsidiaries.
3+
// SPDX-License-Identifier: MPL-2.0
4+
5+
package vsphere
6+
7+
import (
8+
"fmt"
9+
"os"
10+
"testing"
11+
12+
"github.com/hashicorp/terraform-plugin-testing/helper/resource"
13+
"github.com/vmware/terraform-provider-vsphere/vsphere/internal/helper/testhelper"
14+
)
15+
16+
func TestAccDataSourceVSphereConfigProfile(t *testing.T) {
17+
// Run this test manually, do not include in automated testing
18+
t.Skipf("Skipped due to cleanup problems - https://github.com/vmware/terraform-provider-vsphere/issues/2543")
19+
resource.Test(t, resource.TestCase{
20+
PreCheck: func() {
21+
RunSweepers()
22+
testAccPreCheck(t)
23+
},
24+
Providers: testAccProviders,
25+
Steps: []resource.TestStep{
26+
{
27+
Config: testAccDataSourceVSphereConfigProfileConfig(),
28+
Check: resource.ComposeTestCheckFunc(
29+
resource.TestCheckResourceAttrSet("data.vsphere_config_profile.profile2", "config"),
30+
resource.TestCheckResourceAttrSet("data.vsphere_config_profile.profile2", "schema"),
31+
),
32+
},
33+
},
34+
})
35+
}
36+
37+
func testAccDataSourceVSphereConfigProfileConfig() string {
38+
return fmt.Sprintf(`
39+
%s
40+
41+
data "vsphere_host_thumbprint" "thumbprint" {
42+
address = "%s"
43+
insecure = true
44+
}
45+
46+
resource "vsphere_host" "h1" {
47+
hostname = "%s"
48+
username = "root"
49+
password = "%s"
50+
thumbprint = data.vsphere_host_thumbprint.thumbprint.id
51+
52+
datacenter = data.vsphere_datacenter.rootdc1.id
53+
54+
lifecycle {
55+
ignore_changes = ["services"]
56+
}
57+
}
58+
59+
resource "vsphere_compute_cluster" "cluster1" {
60+
name = "cluster1"
61+
datacenter_id = data.vsphere_datacenter.rootdc1.id
62+
host_system_ids = [vsphere_host.h1.id]
63+
}
64+
65+
resource "vsphere_configuration_profile" "profile1" {
66+
reference_host_id = vsphere_host.h1.id
67+
cluster_id = vsphere_compute_cluster.cluster1.id
68+
}
69+
70+
data "vsphere_configuration_profile" "profile2" {
71+
cluster_id = vsphere_config_profile.profile1.cluster_id
72+
}
73+
`,
74+
testhelper.ConfigDataRootDC1(),
75+
os.Getenv("TF_VAR_VSPHERE_ESXI4"),
76+
os.Getenv("TF_VAR_VSPHERE_ESXI4"),
77+
os.Getenv("TF_VAR_VSPHERE_ESXI4_PASSWORD"))
78+
}
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
// © Broadcom. All Rights Reserved.
2+
// The term "Broadcom" refers to Broadcom Inc. and/or its subsidiaries.
3+
// SPDX-License-Identifier: MPL-2.0
4+
5+
package configprofile
6+
7+
import (
8+
"context"
9+
"fmt"
10+
11+
"github.com/hashicorp/terraform-plugin-log/tflog"
12+
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
13+
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
14+
"github.com/vmware/govmomi/vapi/esx/settings/clusters/configuration"
15+
"github.com/vmware/govmomi/vapi/rest"
16+
)
17+
18+
func ReadConfigProfile(ctx context.Context, client *rest.Client, d *schema.ResourceData) diag.Diagnostics {
19+
m := configuration.NewManager(client)
20+
21+
clusterID := d.Get("cluster_id").(string)
22+
23+
d.SetId(fmt.Sprintf("config_profile_%s", clusterID))
24+
25+
tflog.Debug(ctx, fmt.Sprintf("reading configuration for cluster: %s", clusterID))
26+
config, err := m.GetConfiguration(clusterID)
27+
if err != nil {
28+
return diag.FromErr(fmt.Errorf("failed to retrieve cluster configuration: %s", err))
29+
}
30+
31+
_ = d.Set("configuration", config.Config)
32+
33+
tflog.Debug(ctx, fmt.Sprintf("reading configuration schema for cluster: %s", clusterID))
34+
configSchema, err := m.GetSchema(clusterID)
35+
if err != nil {
36+
return diag.FromErr(fmt.Errorf("failed to retrieve configuration schema: %s", err))
37+
}
38+
39+
_ = d.Set("schema", configSchema.Schema)
40+
41+
return nil
42+
}

vsphere/provider.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,7 @@ func Provider() *schema.Provider {
110110
"vsphere_compute_cluster_vm_dependency_rule": resourceVSphereComputeClusterVMDependencyRule(),
111111
"vsphere_compute_cluster_vm_group": resourceVSphereComputeClusterVMGroup(),
112112
"vsphere_compute_cluster_vm_host_rule": resourceVSphereComputeClusterVMHostRule(),
113+
"vsphere_configuration_profile": resourceVSphereConfigurationProfile(),
113114
"vsphere_content_library": resourceVSphereContentLibrary(),
114115
"vsphere_content_library_item": resourceVSphereContentLibraryItem(),
115116
"vsphere_custom_attribute": resourceVSphereCustomAttribute(),
@@ -152,6 +153,7 @@ func Provider() *schema.Provider {
152153
DataSourcesMap: map[string]*schema.Resource{
153154
"vsphere_compute_cluster": dataSourceVSphereComputeCluster(),
154155
"vsphere_compute_cluster_host_group": dataSourceVSphereComputeClusterHostGroup(),
156+
"vsphere_configuration_profile": dataSourceVSphereConfigurationProfile(),
155157
"vsphere_content_library": dataSourceVSphereContentLibrary(),
156158
"vsphere_content_library_item": dataSourceVSphereContentLibraryItem(),
157159
"vsphere_custom_attribute": dataSourceVSphereCustomAttribute(),

0 commit comments

Comments
 (0)