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

HCS-2061: Add size upgrade field for consul cluster update #168

Merged
merged 3 commits into from
Aug 11, 2021
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
25 changes: 6 additions & 19 deletions internal/clients/consul_cluster.go
Original file line number Diff line number Diff line change
Expand Up @@ -164,28 +164,15 @@ func ListConsulUpgradeVersions(ctx context.Context, client *Client, loc *sharedm

// UpdateConsulCluster will make a call to the Consul service to initiate the update Consul
// cluster workflow.
func UpdateConsulCluster(ctx context.Context, client *Client, loc *sharedmodels.HashicorpCloudLocationLocation,
clusterID, newConsulVersion string) (*consulmodels.HashicorpCloudConsul20210204UpdateResponse, error) {

cluster := consulmodels.HashicorpCloudConsul20210204Cluster{
ConsulVersion: newConsulVersion,
ID: clusterID,
Location: &sharedmodels.HashicorpCloudLocationLocation{
ProjectID: loc.ProjectID,
OrganizationID: loc.OrganizationID,
Region: &sharedmodels.HashicorpCloudLocationRegion{
Region: loc.Region.Region,
Provider: loc.Region.Provider,
},
},
}
func UpdateConsulCluster(ctx context.Context, client *Client,
newCluster *consulmodels.HashicorpCloudConsul20210204Cluster) (*consulmodels.HashicorpCloudConsul20210204UpdateResponse, error) {

updateParams := consul_service.NewUpdateParams()
updateParams.Context = ctx
updateParams.ClusterID = cluster.ID
updateParams.ClusterLocationProjectID = loc.ProjectID
updateParams.ClusterLocationOrganizationID = loc.OrganizationID
updateParams.Body = &cluster
updateParams.ClusterID = newCluster.ID
updateParams.ClusterLocationProjectID = newCluster.Location.ProjectID
updateParams.ClusterLocationOrganizationID = newCluster.Location.OrganizationID
updateParams.Body = newCluster

// Invoke update cluster endpoint
updateResp, err := client.Consul.Update(updateParams, nil)
Expand Down
68 changes: 51 additions & 17 deletions internal/provider/resource_consul_cluster.go
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,6 @@ func resourceConsulCluster() *schema.Resource {
Description: "The t-shirt size representation of each server VM that this Consul cluster is provisioned with. Valid option for development tier - `x_small`. Valid options for other tiers - `small`, `medium`, `large`. For more details - https://cloud.hashicorp.com/pricing/consul",
Type: schema.TypeString,
Optional: true,
ForceNew: true,
Computed: true,
ValidateDiagFunc: validateConsulClusterSize,
DiffSuppressFunc: func(_, old, new string, _ *schema.ResourceData) bool {
Expand Down Expand Up @@ -583,30 +582,59 @@ func resourceConsulClusterUpdate(ctx context.Context, d *schema.ResourceData, me
return diag.Errorf("unable to fetch Consul cluster (%s): %v", clusterID, err)
}

// Fetch available upgrade versions
upgradeVersions, err := clients.ListConsulUpgradeVersions(ctx, client, cluster.Location, clusterID)
if err != nil {
return diag.Errorf("unable to list Consul upgrade versions (%s): %v", clusterID, err)
// Confirm update fields have been changed
sizeChanged := d.HasChange("size")
versionChanged := d.HasChange("min_consul_version")

if !sizeChanged && !versionChanged {
return diag.Errorf("at least one of: [min_consul_version, size] is required in order to update the cluster")
}

v, ok := d.GetOk("min_consul_version")
if !ok {
return diag.Errorf("min_consul_version is required in order to upgrade the cluster")
targetCluster := consulmodels.HashicorpCloudConsul20210204Cluster{
ID: clusterID,
Location: &sharedmodels.HashicorpCloudLocationLocation{
ProjectID: cluster.Location.ProjectID,
OrganizationID: cluster.Location.OrganizationID,
Region: &sharedmodels.HashicorpCloudLocationRegion{
Region: cluster.Location.Region.Region,
Provider: cluster.Location.Region.Provider,
},
},
}
newConsulVersion := input.NormalizeVersion(v.(string))

// Check that there are any valid upgrade versions
if upgradeVersions == nil {
return diag.Errorf("no upgrade versions of Consul are available for this cluster; you may already be on the latest Consul version supported by HCP")
if versionChanged {
// Fetch available upgrade versions
upgradeVersions, err := clients.ListConsulUpgradeVersions(ctx, client, cluster.Location, clusterID)
if err != nil {
return diag.Errorf("unable to list Consul upgrade versions (%s): %v", clusterID, err)
}
version := d.Get("min_consul_version")
newConsulVersion := input.NormalizeVersion(version.(string))

// Check that there are any valid upgrade versions
if upgradeVersions == nil {
return diag.Errorf("no upgrade versions of Consul are available for this cluster; you may already be on the latest Consul version supported by HCP")
}

// Validate that the upgrade version is valid
if !consul.IsValidVersion(newConsulVersion, upgradeVersions) {
return diag.Errorf("specified Consul version (%s) is unavailable; must be one of: [%s]", newConsulVersion, consul.VersionsToString(upgradeVersions))
}

targetCluster.ConsulVersion = newConsulVersion
}

// Validate that the upgrade version is valid
if !consul.IsValidVersion(newConsulVersion, upgradeVersions) {
return diag.Errorf("specified Consul version (%s) is unavailable; must be one of: [%s]", newConsulVersion, consul.VersionsToString(upgradeVersions))
if sizeChanged {
newSize := d.Get("size").(string)
targetCluster.Config = &consulmodels.HashicorpCloudConsul20210204ClusterConfig{
CapacityConfig: &consulmodels.HashicorpCloudConsul20210204CapacityConfig{
Size: consulmodels.HashicorpCloudConsul20210204CapacityConfigSize(strings.ToUpper(newSize)),
},
}
}

// Invoke update cluster endpoint
updateResp, err := clients.UpdateConsulCluster(ctx, client, cluster.Location, clusterID, newConsulVersion)
updateResp, err := clients.UpdateConsulCluster(ctx, client, &targetCluster)
if err != nil {
return diag.Errorf("error updating Consul cluster (%s): %v", clusterID, err)
}
Expand All @@ -616,13 +644,19 @@ func resourceConsulClusterUpdate(ctx context.Context, d *schema.ResourceData, me
return diag.Errorf("unable to update Consul cluster (%s): %v", clusterID, err)
}

// Get updated Consul cluster
updatedCluster, err := clients.GetConsulClusterByID(ctx, client, loc, clusterID)
if err != nil {
return diag.Errorf("unable to retrieve Consul cluster (%s): %v", clusterID, err)
}

// get the cluster's Consul client config files
clientConfigFiles, err := clients.GetConsulClientConfigFiles(ctx, client, cluster.Location, clusterID)
if err != nil {
return diag.Errorf("unable to retrieve Consul cluster (%s) client config files: %v", clusterID, err)
}

if err := setConsulClusterResourceData(d, cluster, clientConfigFiles); err != nil {
if err := setConsulClusterResourceData(d, updatedCluster, clientConfigFiles); err != nil {
return diag.FromErr(err)
}

Expand Down
63 changes: 43 additions & 20 deletions internal/provider/resource_consul_cluster_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,27 +10,42 @@ import (
"github.com/hashicorp/terraform-provider-hcp/internal/clients"
)

var testAccConsulClusterConfig = `
resource "hcp_hvn" "test" {
hvn_id = "test-hvn"
cloud_provider = "aws"
region = "us-west-2"
var consulCluster = `
resource "hcp_consul_cluster" "test" {
cluster_id = "test-consul-cluster"
hvn_id = hcp_hvn.test.hvn_id
tier = "standard"
}
`

var updatedConsulCluster = `
resource "hcp_consul_cluster" "test" {
cluster_id = "test-consul-cluster"
hvn_id = hcp_hvn.test.hvn_id
tier = "development"
tier = "standard"
size = "medium"
}
`

data "hcp_consul_cluster" "test" {
cluster_id = hcp_consul_cluster.test.cluster_id
}
func setTestAccConsulClusterConfig(consulCluster string) string {
return fmt.Sprintf(`
resource "hcp_hvn" "test" {
hvn_id = "test-hvn"
cloud_provider = "aws"
region = "us-west-2"
}

resource "hcp_consul_cluster_root_token" "test" {
cluster_id = hcp_consul_cluster.test.cluster_id
%s

data "hcp_consul_cluster" "test" {
cluster_id = hcp_consul_cluster.test.cluster_id
}

resource "hcp_consul_cluster_root_token" "test" {
cluster_id = hcp_consul_cluster.test.cluster_id
}
`, consulCluster)
}
`

// This includes tests against both the resource, the corresponding datasource,
// and creation of the Consul cluster root token resource in order to shorten
Expand All @@ -47,17 +62,17 @@ func TestAccConsulCluster(t *testing.T) {
Steps: []resource.TestStep{
// Tests create
{
Config: testConfig(testAccConsulClusterConfig),
Config: testConfig(setTestAccConsulClusterConfig(consulCluster)),
Check: resource.ComposeTestCheckFunc(
testAccCheckConsulClusterExists(resourceName),
resource.TestCheckResourceAttr(resourceName, "cluster_id", "test-consul-cluster"),
resource.TestCheckResourceAttr(resourceName, "hvn_id", "test-hvn"),
resource.TestCheckResourceAttr(resourceName, "tier", "DEVELOPMENT"),
resource.TestCheckResourceAttr(resourceName, "tier", "STANDARD"),
resource.TestCheckResourceAttr(resourceName, "cloud_provider", "aws"),
resource.TestCheckResourceAttr(resourceName, "region", "us-west-2"),
resource.TestCheckResourceAttr(resourceName, "public_endpoint", "false"),
resource.TestCheckResourceAttr(resourceName, "datacenter", "test-consul-cluster"),
resource.TestCheckResourceAttr(resourceName, "scale", "1"),
resource.TestCheckResourceAttr(resourceName, "scale", "3"),
resource.TestCheckResourceAttr(resourceName, "consul_snapshot_interval", "24h"),
resource.TestCheckResourceAttr(resourceName, "consul_snapshot_retention", "30d"),
resource.TestCheckResourceAttr(resourceName, "connect_enabled", "true"),
Expand Down Expand Up @@ -94,17 +109,17 @@ func TestAccConsulCluster(t *testing.T) {
},
// Tests read
{
Config: testConfig(testAccConsulClusterConfig),
Config: testConfig(setTestAccConsulClusterConfig(consulCluster)),
Check: resource.ComposeTestCheckFunc(
testAccCheckConsulClusterExists(resourceName),
resource.TestCheckResourceAttr(resourceName, "cluster_id", "test-consul-cluster"),
resource.TestCheckResourceAttr(resourceName, "hvn_id", "test-hvn"),
resource.TestCheckResourceAttr(resourceName, "tier", "DEVELOPMENT"),
resource.TestCheckResourceAttr(resourceName, "tier", "STANDARD"),
resource.TestCheckResourceAttr(resourceName, "cloud_provider", "aws"),
resource.TestCheckResourceAttr(resourceName, "region", "us-west-2"),
resource.TestCheckResourceAttr(resourceName, "public_endpoint", "false"),
resource.TestCheckResourceAttr(resourceName, "datacenter", "test-consul-cluster"),
resource.TestCheckResourceAttr(resourceName, "scale", "1"),
resource.TestCheckResourceAttr(resourceName, "scale", "3"),
resource.TestCheckResourceAttr(resourceName, "consul_snapshot_interval", "24h"),
resource.TestCheckResourceAttr(resourceName, "consul_snapshot_retention", "30d"),
resource.TestCheckResourceAttr(resourceName, "connect_enabled", "true"),
Expand All @@ -125,7 +140,7 @@ func TestAccConsulCluster(t *testing.T) {
},
// Tests datasource
{
Config: testConfig(testAccConsulClusterConfig),
Config: testConfig(setTestAccConsulClusterConfig(consulCluster)),
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttrPair(resourceName, "cluster_id", dataSourceName, "cluster_id"),
resource.TestCheckResourceAttrPair(resourceName, "project_id", dataSourceName, "project_id"),
Expand Down Expand Up @@ -154,14 +169,22 @@ func TestAccConsulCluster(t *testing.T) {
},
// Tests root token
{
Config: testConfig(testAccConsulClusterConfig),
Config: testConfig(setTestAccConsulClusterConfig(consulCluster)),
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttr(rootTokenResourceName, "cluster_id", "test-consul-cluster"),
resource.TestCheckResourceAttrSet(rootTokenResourceName, "accessor_id"),
resource.TestCheckResourceAttrSet(rootTokenResourceName, "secret_id"),
resource.TestCheckResourceAttrSet(rootTokenResourceName, "kubernetes_secret"),
),
},
// Tests update
{
Config: testConfig(setTestAccConsulClusterConfig(updatedConsulCluster)),
Check: resource.ComposeTestCheckFunc(
testAccCheckConsulClusterExists(resourceName),
resource.TestCheckResourceAttr(resourceName, "size", "MEDIUM"),
),
},
},
})
}
Expand Down