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

TF changes for AlloyDB Free trials #8042

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
3 changes: 3 additions & 0 deletions .changelog/11207.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
```release-note:enhancement
alloydb: added `subscription_type` and `trial_metadata` field to `google_alloydb_cluster` resource
```
101 changes: 101 additions & 0 deletions google-beta/services/alloydb/resource_alloydb_cluster.go
Original file line number Diff line number Diff line change
Expand Up @@ -481,6 +481,13 @@ It is specified in the form: "projects/{projectNumber}/global/networks/{network_
},
},
},
"subscription_type": {
Type: schema.TypeString,
Computed: true,
Optional: true,
ValidateFunc: verify.ValidateEnum([]string{"TRIAL", "STANDARD", ""}),
Description: `The subscrition type of cluster. Possible values: ["TRIAL", "STANDARD"]`,
},
"backup_source": {
Type: schema.TypeList,
Computed: true,
Expand Down Expand Up @@ -626,6 +633,35 @@ This can happen due to user-triggered updates or system actions like failover or
and default labels configured on the provider.`,
Elem: &schema.Schema{Type: schema.TypeString},
},
"trial_metadata": {
Type: schema.TypeList,
Computed: true,
Description: `Contains information and all metadata related to TRIAL clusters.`,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"end_time": {
Type: schema.TypeString,
Optional: true,
Description: `End time of the trial cluster.`,
},
"grace_end_time": {
Type: schema.TypeString,
Optional: true,
Description: `Grace end time of the trial cluster.`,
},
"start_time": {
Type: schema.TypeString,
Optional: true,
Description: `Start time of the trial cluster.`,
},
"upgrade_time": {
Type: schema.TypeString,
Optional: true,
Description: `Upgrade time of the trial cluster to standard cluster.`,
},
},
},
},
"uid": {
Type: schema.TypeString,
Computed: true,
Expand Down Expand Up @@ -742,6 +778,12 @@ func resourceAlloydbClusterCreate(d *schema.ResourceData, meta interface{}) erro
} else if v, ok := d.GetOkExists("maintenance_update_policy"); !tpgresource.IsEmptyValue(reflect.ValueOf(maintenanceUpdatePolicyProp)) && (ok || !reflect.DeepEqual(v, maintenanceUpdatePolicyProp)) {
obj["maintenanceUpdatePolicy"] = maintenanceUpdatePolicyProp
}
subscriptionTypeProp, err := expandAlloydbClusterSubscriptionType(d.Get("subscription_type"), d, config)
if err != nil {
return err
} else if v, ok := d.GetOkExists("subscription_type"); !tpgresource.IsEmptyValue(reflect.ValueOf(subscriptionTypeProp)) && (ok || !reflect.DeepEqual(v, subscriptionTypeProp)) {
obj["subscriptionType"] = subscriptionTypeProp
}
labelsProp, err := expandAlloydbClusterEffectiveLabels(d.Get("effective_labels"), d, config)
if err != nil {
return err
Expand Down Expand Up @@ -986,6 +1028,12 @@ func resourceAlloydbClusterRead(d *schema.ResourceData, meta interface{}) error
if err := d.Set("maintenance_update_policy", flattenAlloydbClusterMaintenanceUpdatePolicy(res["maintenanceUpdatePolicy"], d, config)); err != nil {
return fmt.Errorf("Error reading Cluster: %s", err)
}
if err := d.Set("subscription_type", flattenAlloydbClusterSubscriptionType(res["subscriptionType"], d, config)); err != nil {
return fmt.Errorf("Error reading Cluster: %s", err)
}
if err := d.Set("trial_metadata", flattenAlloydbClusterTrialMetadata(res["trialMetadata"], d, config)); err != nil {
return fmt.Errorf("Error reading Cluster: %s", err)
}
if err := d.Set("terraform_labels", flattenAlloydbClusterTerraformLabels(res["labels"], d, config)); err != nil {
return fmt.Errorf("Error reading Cluster: %s", err)
}
Expand Down Expand Up @@ -1087,6 +1135,12 @@ func resourceAlloydbClusterUpdate(d *schema.ResourceData, meta interface{}) erro
} else if v, ok := d.GetOkExists("maintenance_update_policy"); !tpgresource.IsEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, maintenanceUpdatePolicyProp)) {
obj["maintenanceUpdatePolicy"] = maintenanceUpdatePolicyProp
}
subscriptionTypeProp, err := expandAlloydbClusterSubscriptionType(d.Get("subscription_type"), d, config)
if err != nil {
return err
} else if v, ok := d.GetOkExists("subscription_type"); !tpgresource.IsEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, subscriptionTypeProp)) {
obj["subscriptionType"] = subscriptionTypeProp
}
labelsProp, err := expandAlloydbClusterEffectiveLabels(d.Get("effective_labels"), d, config)
if err != nil {
return err
Expand Down Expand Up @@ -1157,6 +1211,10 @@ func resourceAlloydbClusterUpdate(d *schema.ResourceData, meta interface{}) erro
updateMask = append(updateMask, "maintenanceUpdatePolicy")
}

if d.HasChange("subscription_type") {
updateMask = append(updateMask, "subscriptionType")
}

if d.HasChange("effective_labels") {
updateMask = append(updateMask, "labels")
}
Expand Down Expand Up @@ -2013,6 +2071,45 @@ func flattenAlloydbClusterMaintenanceUpdatePolicyMaintenanceWindowsStartTimeNano
return v // let terraform core handle it otherwise
}

func flattenAlloydbClusterSubscriptionType(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} {
return v
}

func flattenAlloydbClusterTrialMetadata(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} {
if v == nil {
return nil
}
original := v.(map[string]interface{})
if len(original) == 0 {
return nil
}
transformed := make(map[string]interface{})
transformed["start_time"] =
flattenAlloydbClusterTrialMetadataStartTime(original["startTime"], d, config)
transformed["end_time"] =
flattenAlloydbClusterTrialMetadataEndTime(original["endTime"], d, config)
transformed["upgrade_time"] =
flattenAlloydbClusterTrialMetadataUpgradeTime(original["upgradeTime"], d, config)
transformed["grace_end_time"] =
flattenAlloydbClusterTrialMetadataGraceEndTime(original["graceEndTime"], d, config)
return []interface{}{transformed}
}
func flattenAlloydbClusterTrialMetadataStartTime(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} {
return v
}

func flattenAlloydbClusterTrialMetadataEndTime(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} {
return v
}

func flattenAlloydbClusterTrialMetadataUpgradeTime(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} {
return v
}

func flattenAlloydbClusterTrialMetadataGraceEndTime(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} {
return v
}

func flattenAlloydbClusterTerraformLabels(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} {
if v == nil {
return v
Expand Down Expand Up @@ -2667,6 +2764,10 @@ func expandAlloydbClusterMaintenanceUpdatePolicyMaintenanceWindowsStartTimeNanos
return v, nil
}

func expandAlloydbClusterSubscriptionType(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) {
return v, nil
}

func expandAlloydbClusterEffectiveLabels(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (map[string]string, error) {
if v == nil {
return map[string]string{}, nil
Expand Down
206 changes: 206 additions & 0 deletions google-beta/services/alloydb/resource_alloydb_cluster_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,9 @@ func TestAccAlloydbCluster_update(t *testing.T) {
Steps: []resource.TestStep{
{
Config: testAccAlloydbCluster_alloydbClusterBasicExample(context),
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttr("google_alloydb_cluster.default", "subscription_type", "STANDARD"),
),
},
{
ResourceName: "google_alloydb_cluster.default",
Expand Down Expand Up @@ -74,6 +77,94 @@ resource "google_compute_network" "default" {
`, context)
}

// Trial cluster creation should succeed with subscription type field set to Trial.
func TestAccAlloydbCluster_withSubscriptionTypeTrial(t *testing.T) {
t.Parallel()

context := map[string]interface{}{
"random_suffix": acctest.RandString(t, 10),
}

acctest.VcrTest(t, resource.TestCase{
PreCheck: func() { acctest.AccTestPreCheck(t) },
ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t),
CheckDestroy: testAccCheckAlloydbClusterDestroyProducer(t),
Steps: []resource.TestStep{
{
Config: testAccAlloydbCluster_withSubscriptionTypeTrial(context),
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttr("google_alloydb_cluster.default", "subscription_type", "TRIAL"),
resource.TestMatchResourceAttr("google_alloydb_cluster.default", "trial_metadata.0.start_time", regexp.MustCompile(".+")),
resource.TestMatchResourceAttr("google_alloydb_cluster.default", "trial_metadata.0.end_time", regexp.MustCompile(".+")),
),
},
},
})
}

func testAccAlloydbCluster_withSubscriptionTypeTrial(context map[string]interface{}) string {
return acctest.Nprintf(`
resource "google_alloydb_cluster" "default" {
cluster_id = "tf-test-alloydb-cluster%{random_suffix}"
location = "us-central1"
subscription_type = "TRIAL"
network_config {
network = "projects/${data.google_project.project.number}/global/networks/${google_compute_network.default.name}"
}
}

data "google_project" "project" {
}

resource "google_compute_network" "default" {
name = "tf-test-alloydb-cluster%{random_suffix}"
}
`, context)
}

// Standard cluster creation should succeed with subscription type field set to Standard.
func TestAccAlloydbCluster_withSubscriptionTypeStandard(t *testing.T) {
t.Parallel()

context := map[string]interface{}{
"random_suffix": acctest.RandString(t, 10),
}

acctest.VcrTest(t, resource.TestCase{
PreCheck: func() { acctest.AccTestPreCheck(t) },
ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t),
CheckDestroy: testAccCheckAlloydbClusterDestroyProducer(t),
Steps: []resource.TestStep{
{
Config: testAccAlloydbCluster_withSubscriptionTypeStandard(context),
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttr("google_alloydb_cluster.default", "subscription_type", "STANDARD"),
),
},
},
})
}

func testAccAlloydbCluster_withSubscriptionTypeStandard(context map[string]interface{}) string {
return acctest.Nprintf(`
resource "google_alloydb_cluster" "default" {
cluster_id = "tf-test-alloydb-cluster%{random_suffix}"
location = "us-central1"
subscription_type = "STANDARD"
network_config {
network = "projects/${data.google_project.project.number}/global/networks/${google_compute_network.default.name}"
}
}

data "google_project" "project" {
}

resource "google_compute_network" "default" {
name = "tf-test-alloydb-cluster%{random_suffix}"
}
`, context)
}

// Test if adding automatedBackupPolicy AND initialUser re-creates the cluster.
// Ideally, cluster shouldn't be re-created. This test will only pass if the cluster
// isn't re-created but updated in-place.
Expand Down Expand Up @@ -1365,3 +1456,118 @@ resource "google_alloydb_cluster" "default" {
data "google_project" "project" {}
`, context)
}

// Ensures cluster update from unspecified to standard and standard to standard works with no change in config.
func TestAccAlloydbCluster_standardClusterUpdate(t *testing.T) {
t.Parallel()

context := map[string]interface{}{
"random_suffix": acctest.RandString(t, 10),
}

acctest.VcrTest(t, resource.TestCase{
PreCheck: func() { acctest.AccTestPreCheck(t) },
ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t),
CheckDestroy: testAccCheckAlloydbClusterDestroyProducer(t),
Steps: []resource.TestStep{
{
Config: testAccAlloydbCluster_alloydbClusterBasicExample(context),
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttr("google_alloydb_cluster.default", "subscription_type", "STANDARD"),
),
},
{
ResourceName: "google_alloydb_cluster.default",
ImportState: true,
ImportStateVerify: true,
ImportStateVerifyIgnore: []string{"initial_user", "cluster_id", "location"},
},
{
Config: testAccAlloydbCluster_withSubscriptionTypeStandard(context),
},
{
ResourceName: "google_alloydb_cluster.default",
ImportState: true,
ImportStateVerify: true,
ImportStateVerifyIgnore: []string{"initial_user", "cluster_id", "location"},
},
{
Config: testAccAlloydbCluster_withSubscriptionTypeStandard(context),
},
{
ResourceName: "google_alloydb_cluster.default",
ImportState: true,
ImportStateVerify: true,
ImportStateVerifyIgnore: []string{"initial_user", "cluster_id", "location"},
},
},
})
}

// Ensures cluster update succeeds with subscription type from trial to standard and trial to trial results in no change in config.
func TestAccAlloydbCluster_trialClusterUpdate(t *testing.T) {
t.Parallel()

context := map[string]interface{}{
"random_suffix": acctest.RandString(t, 10),
}

acctest.VcrTest(t, resource.TestCase{
PreCheck: func() { acctest.AccTestPreCheck(t) },
ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t),
CheckDestroy: testAccCheckAlloydbClusterDestroyProducer(t),
Steps: []resource.TestStep{
{
Config: testAccAlloydbCluster_withSubscriptionTypeTrial(context),
},
{
ResourceName: "google_alloydb_cluster.default",
ImportState: true,
ImportStateVerify: true,
ImportStateVerifyIgnore: []string{"initial_user", "cluster_id", "location"},
},
{
Config: testAccAlloydbCluster_withSubscriptionTypeTrial(context),
},
{
ResourceName: "google_alloydb_cluster.default",
ImportState: true,
ImportStateVerify: true,
ImportStateVerifyIgnore: []string{"initial_user", "cluster_id", "location"},
},
{
Config: testAccAlloydbCluster_withSubscriptionTypeStandard(context),
},
{
ResourceName: "google_alloydb_cluster.default",
ImportState: true,
ImportStateVerify: true,
ImportStateVerifyIgnore: []string{"initial_user", "cluster_id", "location"},
},
},
})
}

// Ensures cluster update throws expected errors for subscription update from standard to trial.
func TestAccAlloydbCluster_standardClusterUpdateFailure(t *testing.T) {
t.Parallel()
errorPattern := `.*The request was invalid: invalid subscription_type update`
context := map[string]interface{}{
"random_suffix": acctest.RandString(t, 10),
}

acctest.VcrTest(t, resource.TestCase{
PreCheck: func() { acctest.AccTestPreCheck(t) },
ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t),
CheckDestroy: testAccCheckAlloydbClusterDestroyProducer(t),
Steps: []resource.TestStep{
{
Config: testAccAlloydbCluster_withSubscriptionTypeStandard(context),
},
{
Config: testAccAlloydbCluster_withSubscriptionTypeTrial(context),
ExpectError: regexp.MustCompile(errorPattern),
},
},
})
}
Loading