From f81b4604f049b4791046a46d886750232bb78511 Mon Sep 17 00:00:00 2001 From: upodroid Date: Mon, 28 Sep 2020 23:09:02 +0100 Subject: [PATCH 1/3] add image filter support --- .../data_source_google_compute_image.go | 25 ++++++++- .../data_source_google_compute_image_test.go | 56 +++++++++++++++++++ .../docs/d/compute_image.html.markdown | 5 +- 3 files changed, 81 insertions(+), 5 deletions(-) diff --git a/third_party/terraform/data_sources/data_source_google_compute_image.go b/third_party/terraform/data_sources/data_source_google_compute_image.go index 87da4307a488..3cad073eaf17 100644 --- a/third_party/terraform/data_sources/data_source_google_compute_image.go +++ b/third_party/terraform/data_sources/data_source_google_compute_image.go @@ -19,14 +19,20 @@ func dataSourceGoogleComputeImage() *schema.Resource { Optional: true, ForceNew: true, Computed: true, - ConflictsWith: []string{"family"}, + ConflictsWith: []string{"family", "filter"}, }, "family": { Type: schema.TypeString, Optional: true, ForceNew: true, Computed: true, - ConflictsWith: []string{"name"}, + ConflictsWith: []string{"name", "filter"}, + }, + "filter": { + Type: schema.TypeString, + Optional: true, + ForceNew: true, + ConflictsWith: []string{"name", "family"}, }, "archive_size_bytes": { Type: schema.TypeInt, @@ -121,8 +127,21 @@ func dataSourceGoogleComputeImageRead(d *schema.ResourceData, meta interface{}) log.Printf("[DEBUG] Fetching latest non-deprecated image from family %s", v.(string)) image, err = config.clientCompute.Images.GetFromFamily(project, v.(string)).Do() log.Printf("[DEBUG] Fetched latest non-deprecated image from family %s", v.(string)) + } else if v, ok := d.GetOk("filter"); ok { + images, err := config.clientCompute.Images.List(project).Filter(v.(string)).Do() + if err != nil { + return fmt.Errorf("error retrieving list of images: %s", err) + } + + if len(images.Items) == 1 { + for _, im := range images.Items { + image = im + } + } else { + return fmt.Errorf("Your filter has returned more than one image or no image. Please refine your filter to return exactly one image.") + } } else { - return fmt.Errorf("one of name or family must be set") + return fmt.Errorf("one of name, family or filters must be set") } if err != nil { diff --git a/third_party/terraform/tests/data_source_google_compute_image_test.go b/third_party/terraform/tests/data_source_google_compute_image_test.go index c22f249b2e0f..c0e760eaa4db 100644 --- a/third_party/terraform/tests/data_source_google_compute_image_test.go +++ b/third_party/terraform/tests/data_source_google_compute_image_test.go @@ -40,6 +40,38 @@ func TestAccDataSourceComputeImage(t *testing.T) { }) } +func TestAccDataSourceComputeImageFilter(t *testing.T) { + t.Parallel() + + family := fmt.Sprintf("tf-test-%d", randInt(t)) + name := fmt.Sprintf("tf-test-%d", randInt(t)) + + vcrTest(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckComputeImageDestroyProducer(t), + Steps: []resource.TestStep{ + { + Config: testAccDataSourcePublicImageConfig, + Check: resource.ComposeTestCheckFunc( + testAccDataSourceCheckPublicImage(), + ), + }, + { + Config: testAccDataSourceCustomImageFilter(family, name), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr("data.google_compute_image.from_filter", + "name", name), + resource.TestCheckResourceAttr("data.google_compute_image.from_filter", + "family", family), + resource.TestCheckResourceAttrSet("data.google_compute_image.from_filter", + "self_link"), + ), + }, + }, + }) +} + func testAccDataSourceCheckPublicImage() resource.TestCheckFunc { return func(s *terraform.State) error { data_source_name := "data.google_compute_image.debian" @@ -105,3 +137,27 @@ data "google_compute_image" "from_family" { } `, family, name, name) } + +func testAccDataSourceCustomImageFilter(family, name string) string { + return fmt.Sprintf(` +resource "google_compute_image" "image" { + family = "%s" + name = "%s" + source_disk = google_compute_disk.disk.self_link + labels = { + test = "%s" + } +} + +resource "google_compute_disk" "disk" { + name = "%s-disk" + zone = "us-central1-b" +} + +data "google_compute_image" "from_filter" { + project = google_compute_image.image.project + filter = "labels.test = %s" +} + +`, family, name, name, name, name) +} diff --git a/third_party/terraform/website/docs/d/compute_image.html.markdown b/third_party/terraform/website/docs/d/compute_image.html.markdown index 127cd632016b..19d199abca65 100644 --- a/third_party/terraform/website/docs/d/compute_image.html.markdown +++ b/third_party/terraform/website/docs/d/compute_image.html.markdown @@ -35,10 +35,11 @@ resource "google_compute_instance" "default" { The following arguments are supported: -* `name` or `family` - (Required) The name of a specific image or a family. +* `name`, `family` or `filter` - (Required) The name of a specific image or a family. Exactly one of `name` of `family` must be specified. If `name` is specified, it will fetch the corresponding image. If `family` is specified, it will returns the latest image -that is part of an image family and is not deprecated. +that is part of an image family and is not deprecated. If you specify a filter, your +filter must return exactly one image. Filter syntax can be found [here](https://cloud.google.com/compute/docs/reference/rest/v1/images/list) in the filter section. - - - From 4bb3b9c6b7962a5b165b204dbd1034713f87c632 Mon Sep 17 00:00:00 2001 From: upodroid Date: Wed, 30 Sep 2020 23:13:23 +0100 Subject: [PATCH 2/3] fix typos in documentation --- .../data_source_google_compute_image.go | 28 +++++++++---------- .../docs/d/compute_image.html.markdown | 6 ++-- 2 files changed, 17 insertions(+), 17 deletions(-) diff --git a/third_party/terraform/data_sources/data_source_google_compute_image.go b/third_party/terraform/data_sources/data_source_google_compute_image.go index 3cad073eaf17..02a5b0cde7e0 100644 --- a/third_party/terraform/data_sources/data_source_google_compute_image.go +++ b/third_party/terraform/data_sources/data_source_google_compute_image.go @@ -15,24 +15,24 @@ func dataSourceGoogleComputeImage() *schema.Resource { Schema: map[string]*schema.Schema{ "name": { - Type: schema.TypeString, - Optional: true, - ForceNew: true, - Computed: true, - ConflictsWith: []string{"family", "filter"}, + Type: schema.TypeString, + Optional: true, + ForceNew: true, + Computed: true, + ExactlyOneOf: []string{"name", "family", "filter"}, }, "family": { - Type: schema.TypeString, - Optional: true, - ForceNew: true, - Computed: true, - ConflictsWith: []string{"name", "filter"}, + Type: schema.TypeString, + Optional: true, + ForceNew: true, + Computed: true, + ExactlyOneOf: []string{"name", "family", "filter"}, }, "filter": { - Type: schema.TypeString, - Optional: true, - ForceNew: true, - ConflictsWith: []string{"name", "family"}, + Type: schema.TypeString, + Optional: true, + ForceNew: true, + ExactlyOneOf: []string{"name", "family", "filter"}, }, "archive_size_bytes": { Type: schema.TypeInt, diff --git a/third_party/terraform/website/docs/d/compute_image.html.markdown b/third_party/terraform/website/docs/d/compute_image.html.markdown index 19d199abca65..e980e537bb1b 100644 --- a/third_party/terraform/website/docs/d/compute_image.html.markdown +++ b/third_party/terraform/website/docs/d/compute_image.html.markdown @@ -36,9 +36,9 @@ resource "google_compute_instance" "default" { The following arguments are supported: * `name`, `family` or `filter` - (Required) The name of a specific image or a family. -Exactly one of `name` of `family` must be specified. If `name` is specified, it will fetch -the corresponding image. If `family` is specified, it will returns the latest image -that is part of an image family and is not deprecated. If you specify a filter, your +Exactly one of `name`, `family` or `filter` must be specified. If `name` is specified, it will fetch +the corresponding image. If `family` is specified, it will return the latest image +that is part of an image family and is not deprecated. If you specify `filter`, your filter must return exactly one image. Filter syntax can be found [here](https://cloud.google.com/compute/docs/reference/rest/v1/images/list) in the filter section. - - - From 5c82a20e605108f5fbd6aff13fd805ced356104d Mon Sep 17 00:00:00 2001 From: upodroid Date: Fri, 9 Oct 2020 21:37:52 +0100 Subject: [PATCH 3/3] fix client function --- .../data_sources/data_source_google_compute_image.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/third_party/terraform/data_sources/data_source_google_compute_image.go b/third_party/terraform/data_sources/data_source_google_compute_image.go index 282e8f0bf6d7..dde16ed26363 100644 --- a/third_party/terraform/data_sources/data_source_google_compute_image.go +++ b/third_party/terraform/data_sources/data_source_google_compute_image.go @@ -132,7 +132,7 @@ func dataSourceGoogleComputeImageRead(d *schema.ResourceData, meta interface{}) image, err = config.NewComputeClient(userAgent).Images.GetFromFamily(project, v.(string)).Do() log.Printf("[DEBUG] Fetched latest non-deprecated image from family %s", v.(string)) } else if v, ok := d.GetOk("filter"); ok { - images, err := config.clientCompute.Images.List(project).Filter(v.(string)).Do() + images, err := config.NewComputeClient(userAgent).Images.List(project).Filter(v.(string)).Do() if err != nil { return fmt.Errorf("error retrieving list of images: %s", err) } @@ -142,7 +142,7 @@ func dataSourceGoogleComputeImageRead(d *schema.ResourceData, meta interface{}) image = im } } else { - return fmt.Errorf("Your filter has returned more than one image or no image. Please refine your filter to return exactly one image.") + return fmt.Errorf("your filter has returned more than one image or no image. Please refine your filter to return exactly one image") } } else { return fmt.Errorf("one of name, family or filters must be set")