Skip to content
Open
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
20 changes: 11 additions & 9 deletions mmv1/products/compute/FutureReservation.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -60,8 +60,6 @@ examples:
end_time: 'time.Date(time.Now().Year(), 12, 31, 0, 0, 0, 0, time.Now().Location()).AddDate(0, 0, 10).Format(time.RFC3339)'
test_env_vars:
project: 'PROJECT_NAME'
org_id: 'ORG_ID'
billing_account: 'BILLING_ACCT'
- name: 'future_reservation_aggregate_reservation'
primary_resource_id: 'gce_future_reservation'
vars:
Expand All @@ -73,8 +71,6 @@ examples:
end_time: 'time.Date(time.Now().Year(), 12, 31, 0, 0, 0, 0, time.Now().Location()).AddDate(0, 0, 10).Format(time.RFC3339)'
test_env_vars:
project: 'PROJECT_NAME'
org_id: 'ORG_ID'
billing_account: 'BILLING_ACCT'
# Skip in VCR until the test issue is resolved
# https://github.com/hashicorp/terraform-provider-google/issues/25087
skip_vcr: true
Expand Down Expand Up @@ -104,16 +100,20 @@ parameters:
RFC1035. Specifically, the name must be 1-63 characters long and match
the regular expression `[a-z]([-a-z0-9]*[a-z0-9])?` which means the
first character must be a lowercase letter, and all following
characters must be a dash, lowercase letter, or digit, except the las
characters must be a dash, lowercase letter, or digit, except the last
character, which cannot be a dash.
required: true
immutable: true
properties:
- name: 'zone'
type: String
type: ResourceRef
description: |
URL of the Zone where this future reservation resides.
output: true
The zone where the future reservation is located.
required: true
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

We can't move a field from output-only to required without a breaking change. Why is this becoming required now?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

In google cloud API future reservations are zone based, for endpoint you need to sent which zone you are consuming reservation from. Variables that construct the url have to be under parameters: . if zone was left where it was users wouldn't be able to provide it in their .tf config

immutable: true
custom_expand: 'templates/terraform/custom_expand/resourceref_with_validation.go.tmpl'
resource: 'Zone'
imports: 'name'
properties:
- name: 'creationTimestamp'
type: Time
description: |
Expand All @@ -139,10 +139,12 @@ properties:
description: |
Start time of the future reservation in RFC3339 format.
required: true
diff_suppress_func: 'tpgresource.Rfc3339TimeDiffSuppress'
- name: 'endTime'
type: String
description: |
End time of the future reservation in RFC3339 format.
diff_suppress_func: 'tpgresource.Rfc3339TimeDiffSuppress'
- name: 'duration'
type: NestedObject
description: |
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ resource "google_compute_future_reservation" "{{$.PrimaryResourceId}}" {
provider = google-beta
name = "{{index $.Vars "future_reservation_name"}}"
project = "{{index $.TestEnvVars "project"}}"
zone = "us-central1-a"
auto_delete_auto_created_reservations = true
planning_status = "DRAFT"
name_prefix = "fr-basic"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ resource "google_compute_future_reservation" "{{$.PrimaryResourceId}}" {
provider = google-beta
name = "{{index $.Vars "future_reservation_name"}}"
project = "{{index $.TestEnvVars "project"}}"
zone = "us-central1-a"
auto_delete_auto_created_reservations = true
planning_status = "DRAFT"
name_prefix = "fr-basic"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ resource "google_compute_future_reservation" "{{$.PrimaryResourceId}}" {
provider = google-beta
project = google_project.owner_project.project_id
name = "{{index $.Vars "future_reservation_name"}}"
zone = "us-central1-a"
auto_delete_auto_created_reservations = true
time_window {
start_time = "{{ index $.Vars "start_time" }}"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ resource "google_compute_future_reservation" "gce_future_reservation" {
name = "tf-test-fr%{random_suffix}"
name_prefix = "fr-%{random_suffix}"
project = "%{project}"
zone = "us-central1-a"
planning_status = "DRAFT"
auto_delete_auto_created_reservations = true
description = "test future reservation"
Expand All @@ -84,6 +85,7 @@ resource "google_compute_future_reservation" "gce_future_reservation" {
name = "tf-test-fr%{random_suffix}"
name_prefix = "fru-%{random_suffix}"
project = "%{project}"
zone = "us-central1-a"
planning_status = "SUBMITTED"
auto_delete_auto_created_reservations = false
description = "test updated future reservation"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1129,12 +1129,13 @@ func ResourceComputeInstance() *schema.Resource {
},

"provisioning_model": {
Type: schema.TypeString,
Optional: true,
Computed: true,
ForceNew: true,
AtLeastOneOf: schedulingKeys,
Description: `Whether the instance is spot. If this is set as SPOT.`,
Type: schema.TypeString,
Optional: true,
Computed: true,
ForceNew: true,
AtLeastOneOf: schedulingKeys,
ValidateFunc: validation.StringInSlice([]string{"", "STANDARD", "SPOT", "FLEX_START", "RESERVATION_BOUND"}, false),
Description: `Describes the desired provisioning model for the instance. For STANDARD, resources are provisioned immediately. For SPOT, resources are offered at a discount compared to standard pricing but may be preempted. For FLEX_START, resources are offered at a discount with flexible start times. For RESERVATION_BOUND, the instance is bound to a specific reservation and will only consume capacity from that reservation.`,
},

"instance_termination_action": {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -804,12 +804,13 @@ Google Cloud KMS. Only one of kms_key_self_link, rsa_encrypted_key and raw_key m
Description: `Minimum number of cpus for the instance.`,
},
"provisioning_model": {
Type: schema.TypeString,
Optional: true,
Computed: true,
ForceNew: true,
AtLeastOneOf: schedulingInstTemplateKeys,
Description: `Whether the instance is spot. If this is set as SPOT.`,
Type: schema.TypeString,
Optional: true,
Computed: true,
ForceNew: true,
AtLeastOneOf: schedulingInstTemplateKeys,
ValidateFunc: validation.StringInSlice([]string{"", "STANDARD", "SPOT", "FLEX_START", "RESERVATION_BOUND"}, false),
Description: `Describes the desired provisioning model for the instance. For STANDARD, resources are provisioned immediately. For SPOT, resources are offered at a discount compared to standard pricing but may be preempted. For FLEX_START, resources are offered at a discount with flexible start times. For RESERVATION_BOUND, the instance is bound to a specific reservation and will only consume capacity from that reservation.`,
},
"instance_termination_action": {
Type: schema.TypeString,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1309,6 +1309,95 @@ func TestAccComputeInstanceTemplate_managedEnvoy(t *testing.T) {
})
}

func TestAccComputeInstanceTemplate_flexStart(t *testing.T) {
t.Parallel()

var instanceTemplate compute.InstanceTemplate
acctest.VcrTest(t, resource.TestCase{
PreCheck: func() { acctest.AccTestPreCheck(t) },
ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t),
CheckDestroy: testAccCheckComputeInstanceTemplateDestroyProducer(t),
Steps: []resource.TestStep{
{
Config: testAccComputeInstanceTemplate_flexStart(acctest.RandString(t, 10)),
Check: resource.ComposeTestCheckFunc(
testAccCheckComputeInstanceTemplateExists(
t, "google_compute_instance_template.foobar", &instanceTemplate),
testAccCheckComputeInstanceTemplateAutomaticRestart(&instanceTemplate, false),
testAccCheckComputeInstanceTemplateProvisioningModel(&instanceTemplate, "FLEX_START"),
testAccCheckComputeInstanceTemplateInstanceTerminationAction(&instanceTemplate, "DELETE"),
),
},
{
ResourceName: "google_compute_instance_template.foobar",
ImportState: true,
ImportStateVerify: true,
},
},
})
}

{{- if ne $.TargetVersionName "ga" }}
func TestAccComputeInstanceTemplate_reservationBound(t *testing.T) {
t.Parallel()

var instanceTemplate compute.InstanceTemplate
suffix := acctest.RandString(t, 10)
context := map[string]interface{}{
"suffix": suffix,
"reservation_name": fmt.Sprintf("tf-test-res-%s", suffix),
}

acctest.VcrTest(t, resource.TestCase{
PreCheck: func() { acctest.AccTestPreCheck(t) },
ProtoV5ProviderFactories: acctest.ProtoV5ProviderBetaFactories(t),
CheckDestroy: testAccCheckComputeInstanceTemplateDestroyProducer(t),
Steps: []resource.TestStep{
{
Config: testAccComputeInstanceTemplate_reservationBound(context),
Check: resource.ComposeTestCheckFunc(
testAccCheckComputeInstanceTemplateExists(
t, "google_compute_instance_template.foobar", &instanceTemplate),
testAccCheckComputeInstanceTemplateAutomaticRestart(&instanceTemplate, false),
testAccCheckComputeInstanceTemplateProvisioningModel(&instanceTemplate, "RESERVATION_BOUND"),
testAccCheckComputeInstanceTemplateInstanceTerminationAction(&instanceTemplate, "DELETE"),
),
},
{
ResourceName: "google_compute_instance_template.foobar",
ImportState: true,
ImportStateVerify: true,
},
},
})
}
{{- end }}

func TestAccComputeInstanceTemplate_provisioningModelEmptyString(t *testing.T) {
t.Parallel()

var instanceTemplate compute.InstanceTemplate
acctest.VcrTest(t, resource.TestCase{
PreCheck: func() { acctest.AccTestPreCheck(t) },
ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t),
CheckDestroy: testAccCheckComputeInstanceTemplateDestroyProducer(t),
Steps: []resource.TestStep{
{
Config: testAccComputeInstanceTemplate_provisioningModelEmptyString(acctest.RandString(t, 10)),
Check: resource.ComposeTestCheckFunc(
testAccCheckComputeInstanceTemplateExists(
t, "google_compute_instance_template.foobar", &instanceTemplate),
),
},
{
ResourceName: "google_compute_instance_template.foobar",
ImportState: true,
ImportStateVerify: true,
},
},
})
}

func TestAccComputeInstanceTemplate_spot(t *testing.T) {
t.Parallel()

Expand Down Expand Up @@ -4992,6 +5081,128 @@ resource "google_compute_instance_template" "foobar" {
`, suffix)
}

func testAccComputeInstanceTemplate_flexStart(suffix string) string {
return fmt.Sprintf(`
data "google_compute_image" "my_image" {
family = "debian-11"
project = "debian-cloud"
}

resource "google_compute_instance_template" "foobar" {
name = "tf-test-instance-template-%s"
machine_type = "e2-medium"
can_ip_forward = false
tags = ["foo", "bar"]

disk {
source_image = data.google_compute_image.my_image.self_link
auto_delete = true
boot = true
}

network_interface {
network = "default"
}

scheduling {
automatic_restart = false
provisioning_model = "FLEX_START"
instance_termination_action = "DELETE"
on_host_maintenance = "TERMINATE"
max_run_duration {
nanos = 0
seconds = 3600
}
}

metadata = {
foo = "bar"
}

service_account {
scopes = ["userinfo-email", "compute-ro", "storage-ro"]
}
}
`, suffix)
}

{{- if ne $.TargetVersionName "ga" }}
func testAccComputeInstanceTemplate_reservationBound(context map[string]interface{}) string {
return acctest.Nprintf(`
resource "google_compute_instance_template" "foobar" {
provider = google-beta
name = "tf-test-instance-template-%{suffix}"
machine_type = "n2-standard-2"
can_ip_forward = false
tags = ["foo", "bar"]

disk {
source_image = "debian-cloud/debian-11"
auto_delete = true
boot = true
}

network_interface {
network = "default"
}

scheduling {
automatic_restart = false
provisioning_model = "RESERVATION_BOUND"
instance_termination_action = "DELETE"
on_host_maintenance = "TERMINATE"
}

reservation_affinity {
type = "SPECIFIC_RESERVATION"
specific_reservation {
key = "compute.googleapis.com/reservation-name"
values = ["%{reservation_name}"]
}
}

metadata = {
foo = "bar"
}

service_account {
scopes = ["userinfo-email", "compute-ro", "storage-ro"]
}
}
`, context)
}
{{- end }}

func testAccComputeInstanceTemplate_provisioningModelEmptyString(suffix string) string {
return fmt.Sprintf(`
data "google_compute_image" "my_image" {
family = "debian-11"
project = "debian-cloud"
}

resource "google_compute_instance_template" "foobar" {
name = "tf-test-instance-template-%s"
machine_type = "e2-medium"
can_ip_forward = false

disk {
source_image = data.google_compute_image.my_image.self_link
auto_delete = true
boot = true
}

network_interface {
network = "default"
}

scheduling {
automatic_restart = false
provisioning_model = ""
}
}
`, suffix)
}

func testAccComputeInstanceTemplate_spot(suffix string) string {
return fmt.Sprintf(`
data "google_compute_image" "my_image" {
Expand Down
Loading
Loading