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

Add new data source google_compute_instance_template #8137

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/4362.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
```release-note:new-datasource
`google_compute_instance_template`
```
91 changes: 91 additions & 0 deletions google/data_source_google_compute_instance_template.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
package google

import (
"fmt"
"sort"

"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
computeBeta "google.golang.org/api/compute/v0.beta"
)

func dataSourceGoogleComputeInstanceTemplate() *schema.Resource {
// Generate datasource schema from resource
dsSchema := datasourceSchemaFromResourceSchema(resourceComputeInstanceTemplate().Schema)

dsSchema["filter"] = &schema.Schema{
Type: schema.TypeString,
Optional: true,
}
dsSchema["most_recent"] = &schema.Schema{
Type: schema.TypeBool,
Optional: true,
}

// Set 'Required' schema elements
addRequiredFieldsToSchema(dsSchema, "project")

// Set 'Optional' schema elements
addOptionalFieldsToSchema(dsSchema, "name", "filter", "most_recent")

dsSchema["name"].ExactlyOneOf = []string{"name", "filter"}
dsSchema["filter"].ExactlyOneOf = []string{"name", "filter"}

return &schema.Resource{
Read: datasourceComputeInstanceTemplateRead,
Schema: dsSchema,
}
}

func datasourceComputeInstanceTemplateRead(d *schema.ResourceData, meta interface{}) error {
config := meta.(*Config)

project, err := getProject(d, config)
if err != nil {
return err
}

if v, ok := d.GetOk("name"); ok {
return retrieveInstance(d, meta, project, v.(string))
}
if v, ok := d.GetOk("filter"); ok {
userAgent, err := generateUserAgentString(d, config.userAgent)
if err != nil {
return err
}

templates, err := config.NewComputeBetaClient(userAgent).InstanceTemplates.List(project).Filter(v.(string)).Do()
if err != nil {
return fmt.Errorf("error retrieving list of instance templates: %s", err)
}

mostRecent := d.Get("most_recent").(bool)
if mostRecent {
sort.Sort(ByCreationTimestamp(templates.Items))
}

count := len(templates.Items)
if count == 1 || count > 1 && mostRecent {
return retrieveInstance(d, meta, project, templates.Items[0].Name)
}

return fmt.Errorf("your filter has returned %d instance template(s). Please refine your filter or set most_recent to return exactly one instance template", len(templates.Items))
}

return fmt.Errorf("one of name or filters must be set")
}

func retrieveInstance(d *schema.ResourceData, meta interface{}, project, name string) error {
d.SetId("projects/" + project + "/global/instanceTemplates/" + name)

return resourceComputeInstanceTemplateRead(d, meta)
}

// ByCreationTimestamp implements sort.Interface for []*InstanceTemplate based on
// the CreationTimestamp field.
type ByCreationTimestamp []*computeBeta.InstanceTemplate

func (a ByCreationTimestamp) Len() int { return len(a) }
func (a ByCreationTimestamp) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
func (a ByCreationTimestamp) Less(i, j int) bool {
return a[i].CreationTimestamp > a[j].CreationTimestamp
}
248 changes: 248 additions & 0 deletions google/data_source_google_compute_instance_template_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,248 @@
package google

import (
"testing"

"github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
)

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

vcrTest(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
Steps: []resource.TestStep{
{
Config: testAccInstanceTemplate_name(getTestProjectFromEnv(), randString(t, 10)),
Check: resource.ComposeTestCheckFunc(
checkDataSourceStateMatchesResourceStateWithIgnores(
"data.google_compute_instance_template.default",
"google_compute_instance_template.default",
map[string]struct{}{},
),
),
},
},
})
}

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

vcrTest(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
Steps: []resource.TestStep{
{
Config: testAccInstanceTemplate_filter(getTestProjectFromEnv(), randString(t, 10)),
Check: resource.ComposeTestCheckFunc(
checkDataSourceStateMatchesResourceStateWithIgnores(
"data.google_compute_instance_template.default",
"google_compute_instance_template.c",
map[string]struct{}{},
),
),
},
},
})
}

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

vcrTest(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
Steps: []resource.TestStep{
{
Config: testAccInstanceTemplate_filter_mostRecent(getTestProjectFromEnv(), randString(t, 10)),
Check: resource.ComposeTestCheckFunc(
checkDataSourceStateMatchesResourceStateWithIgnores(
"data.google_compute_instance_template.default",
"google_compute_instance_template.c",
map[string]struct{}{},
),
),
},
},
})
}

func testAccInstanceTemplate_name(project, suffix string) string {
return Nprintf(`
resource "google_compute_instance_template" "default" {
name = "test-template-%{suffix}"
description = "Example template."

machine_type = "e2-small"

tags = ["foo", "bar"]

disk {
source_image = "cos-cloud/cos-stable"
auto_delete = true
boot = true
}

network_interface {
network = "default"
}
}

data "google_compute_instance_template" "default" {
project = "%{project}"
name = google_compute_instance_template.default.name
}
`, map[string]interface{}{"project": project, "suffix": suffix})
}

func testAccInstanceTemplate_filter(project, suffix string) string {
return Nprintf(`
resource "google_compute_instance_template" "a" {
name = "test-template-a-%{suffix}"
description = "Example template."

machine_type = "e2-small"

tags = ["foo", "bar", "a"]

disk {
source_image = "cos-cloud/cos-stable"
auto_delete = true
boot = true
}

network_interface {
network = "default"
}
}
resource "google_compute_instance_template" "b" {
name = "test-template-b-%{suffix}"
description = "Example template."

machine_type = "e2-small"

tags = ["foo", "bar", "b"]

disk {
source_image = "cos-cloud/cos-stable"
auto_delete = true
boot = true
}

network_interface {
network = "default"
}
}
resource "google_compute_instance_template" "c" {
name = "test-template-c-%{suffix}"
description = "Example template."

machine_type = "e2-small"

tags = ["foo", "bar", "c"]

disk {
source_image = "cos-cloud/cos-stable"
auto_delete = true
boot = true
}

network_interface {
network = "default"
}
}

data "google_compute_instance_template" "default" {
project = "%{project}"
filter = "name eq test-template-c-.*"

depends_on = [
google_compute_instance_template.a,
google_compute_instance_template.b,
google_compute_instance_template.c,
]
}
`, map[string]interface{}{"project": project, "suffix": suffix})
}

func testAccInstanceTemplate_filter_mostRecent(project, suffix string) string {
return Nprintf(`
resource "google_compute_instance_template" "a" {
name = "test-template-%{suffix}-a"
description = "Example template."

machine_type = "e2-small"

tags = ["foo", "bar", "a"]

disk {
source_image = "cos-cloud/cos-stable"
auto_delete = true
boot = true
}

network_interface {
network = "default"
}
}
resource "google_compute_instance_template" "b" {
name = "test-template-%{suffix}-b"
description = "Example template."

machine_type = "e2-small"

tags = ["foo", "bar", "b"]

disk {
source_image = "cos-cloud/cos-stable"
auto_delete = true
boot = true
}

network_interface {
network = "default"
}

depends_on = [
google_compute_instance_template.a,
]
}
resource "google_compute_instance_template" "c" {
name = "test-template-%{suffix}-c"
description = "Example template."

machine_type = "e2-small"

tags = ["foo", "bar", "c"]

disk {
source_image = "cos-cloud/cos-stable"
auto_delete = true
boot = true
}

network_interface {
network = "default"
}

depends_on = [
google_compute_instance_template.a,
google_compute_instance_template.b,
]
}

data "google_compute_instance_template" "default" {
project = "%{project}"
filter = "name eq test-template-.*"
most_recent = true

depends_on = [
google_compute_instance_template.a,
google_compute_instance_template.b,
google_compute_instance_template.c,
]
}
`, map[string]interface{}{"project": project, "suffix": suffix})
}
3 changes: 2 additions & 1 deletion google/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -632,8 +632,9 @@ func Provider() *schema.Provider {
"google_compute_global_forwarding_rule": dataSourceGoogleComputeGlobalForwardingRule(),
"google_compute_image": dataSourceGoogleComputeImage(),
"google_compute_instance": dataSourceGoogleComputeInstance(),
"google_compute_instance_serial_port": dataSourceGoogleComputeInstanceSerialPort(),
"google_compute_instance_group": dataSourceGoogleComputeInstanceGroup(),
"google_compute_instance_serial_port": dataSourceGoogleComputeInstanceSerialPort(),
"google_compute_instance_template": dataSourceGoogleComputeInstanceTemplate(),
"google_compute_lb_ip_ranges": dataSourceGoogleComputeLbIpRanges(),
"google_compute_network": dataSourceGoogleComputeNetwork(),
"google_compute_network_endpoint_group": dataSourceGoogleComputeNetworkEndpointGroup(),
Expand Down
Loading