From c8062cc8b3061cec9bed1564027e0461860b7bfe Mon Sep 17 00:00:00 2001 From: Rens Sikma Date: Thu, 6 Feb 2020 10:27:01 +0100 Subject: [PATCH 1/2] fix #8679 with source_image_project_id as list --- builder/googlecompute/config.go | 4 ++-- builder/googlecompute/config.hcl2spec.go | 4 ++-- builder/googlecompute/driver.go | 5 +++++ builder/googlecompute/driver_gce.go | 5 ++++- builder/googlecompute/driver_mock.go | 15 +++++++++++---- builder/googlecompute/step_create_instance.go | 4 ++-- .../googlecompute-export/post-processor.go | 2 +- .../googlecompute/_Config-not-required.html.md | 2 +- 8 files changed, 28 insertions(+), 13 deletions(-) diff --git a/builder/googlecompute/config.go b/builder/googlecompute/config.go index 0b6c3c267..b45357f26 100644 --- a/builder/googlecompute/config.go +++ b/builder/googlecompute/config.go @@ -149,8 +149,8 @@ type Config struct { // family always returns its latest image that is not deprecated. Example: // "debian-8". SourceImageFamily string `mapstructure:"source_image_family" required:"true"` - // The project ID of the project containing the source image. - SourceImageProjectId string `mapstructure:"source_image_project_id" required:"false"` + // The project ID's of the project containing the source image. + SourceImageProjectId []string `mapstructure:"source_image_project_id" required:"false"` // The path to a startup script to run on the VM from which the image will // be made. StartupScriptFile string `mapstructure:"startup_script_file" required:"false"` diff --git a/builder/googlecompute/config.hcl2spec.go b/builder/googlecompute/config.hcl2spec.go index acc64f1c9..deda6820e 100644 --- a/builder/googlecompute/config.hcl2spec.go +++ b/builder/googlecompute/config.hcl2spec.go @@ -88,7 +88,7 @@ type FlatConfig struct { ServiceAccountEmail *string `mapstructure:"service_account_email" required:"false" cty:"service_account_email"` SourceImage *string `mapstructure:"source_image" required:"true" cty:"source_image"` SourceImageFamily *string `mapstructure:"source_image_family" required:"true" cty:"source_image_family"` - SourceImageProjectId *string `mapstructure:"source_image_project_id" required:"false" cty:"source_image_project_id"` + SourceImageProjectId []string `mapstructure:"source_image_project_id" required:"false" cty:"source_image_project_id"` StartupScriptFile *string `mapstructure:"startup_script_file" required:"false" cty:"startup_script_file"` Subnetwork *string `mapstructure:"subnetwork" required:"false" cty:"subnetwork"` Tags []string `mapstructure:"tags" required:"false" cty:"tags"` @@ -188,7 +188,7 @@ func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec { "service_account_email": &hcldec.AttrSpec{Name: "service_account_email", Type: cty.String, Required: false}, "source_image": &hcldec.AttrSpec{Name: "source_image", Type: cty.String, Required: false}, "source_image_family": &hcldec.AttrSpec{Name: "source_image_family", Type: cty.String, Required: false}, - "source_image_project_id": &hcldec.AttrSpec{Name: "source_image_project_id", Type: cty.String, Required: false}, + "source_image_project_id": &hcldec.AttrSpec{Name: "source_image_project_id", Type: cty.List(cty.String), Required: false}, "startup_script_file": &hcldec.AttrSpec{Name: "startup_script_file", Type: cty.String, Required: false}, "subnetwork": &hcldec.AttrSpec{Name: "subnetwork", Type: cty.String, Required: false}, "tags": &hcldec.AttrSpec{Name: "tags", Type: cty.List(cty.String), Required: false}, diff --git a/builder/googlecompute/driver.go b/builder/googlecompute/driver.go index 7ede0ae2b..e7d34e10d 100644 --- a/builder/googlecompute/driver.go +++ b/builder/googlecompute/driver.go @@ -29,6 +29,11 @@ type Driver interface { // particular image. GetImage(name string, fromFamily bool) (*Image, error) + // GetImageFromProject gets an image from a specific projects. + // Returns the image from the first project in slice it can find one + // If fromFamily is true, name designates an image family instead of a particular image. + GetImageFromProjects(project []string, name string, fromFamily bool) (*Image, error) + // GetImageFromProject gets an image from a specific project. If fromFamily // is true, name designates an image family instead of a particular image. GetImageFromProject(project, name string, fromFamily bool) (*Image, error) diff --git a/builder/googlecompute/driver_gce.go b/builder/googlecompute/driver_gce.go index eea002d3a..ea68b6d65 100644 --- a/builder/googlecompute/driver_gce.go +++ b/builder/googlecompute/driver_gce.go @@ -210,8 +210,8 @@ func (d *driverGCE) DeleteDisk(zone, name string) (<-chan error, error) { go waitForState(errCh, "DONE", d.refreshZoneOp(zone, op)) return errCh, nil } - func (d *driverGCE) GetImage(name string, fromFamily bool) (*Image, error) { + projects := []string{ d.projectId, // Public projects, drawn from @@ -234,6 +234,9 @@ func (d *driverGCE) GetImage(name string, fromFamily bool) (*Image, error) { "google-containers", "opensuse-cloud", } + return d.GetImageFromProjects(projects, name, fromFamily) +} +func (d *driverGCE) GetImageFromProjects(projects []string, name string, fromFamily bool) (*Image, error) { var errs error for _, project := range projects { image, err := d.GetImageFromProject(project, name, fromFamily) diff --git a/builder/googlecompute/driver_mock.go b/builder/googlecompute/driver_mock.go index fed2cccab..080772e5b 100644 --- a/builder/googlecompute/driver_mock.go +++ b/builder/googlecompute/driver_mock.go @@ -36,10 +36,11 @@ type DriverMock struct { DeleteDiskErrCh <-chan error DeleteDiskErr error - GetImageName string - GetImageFromFamily bool - GetImageResult *Image - GetImageErr error + GetImageName string + GetImageSourceProjects []string + GetImageFromFamily bool + GetImageResult *Image + GetImageErr error GetImageFromProjectProject string GetImageFromProjectName string @@ -179,6 +180,12 @@ func (d *DriverMock) GetImage(name string, fromFamily bool) (*Image, error) { d.GetImageFromFamily = fromFamily return d.GetImageResult, d.GetImageErr } +func (d *DriverMock) GetImageFromProjects(projects []string, name string, fromFamily bool) (*Image, error) { + d.GetImageSourceProjects = projects + d.GetImageFromProjectName = name + d.GetImageFromProjectFromFamily = fromFamily + return d.GetImageFromProjectResult, d.GetImageFromProjectErr +} func (d *DriverMock) GetImageFromProject(project, name string, fromFamily bool) (*Image, error) { d.GetImageFromProjectProject = project diff --git a/builder/googlecompute/step_create_instance.go b/builder/googlecompute/step_create_instance.go index 088c88925..9f94eb7ae 100644 --- a/builder/googlecompute/step_create_instance.go +++ b/builder/googlecompute/step_create_instance.go @@ -83,10 +83,10 @@ func getImage(c *Config, d Driver) (*Image, error) { name = c.SourceImage fromFamily = false } - if c.SourceImageProjectId == "" { + if len(c.SourceImageProjectId) == 0 { return d.GetImage(name, fromFamily) } else { - return d.GetImageFromProject(c.SourceImageProjectId, name, fromFamily) + return d.GetImageFromProjects(c.SourceImageProjectId, name, fromFamily) } } diff --git a/post-processor/googlecompute-export/post-processor.go b/post-processor/googlecompute-export/post-processor.go index 16453742a..4f21e4fde 100644 --- a/post-processor/googlecompute-export/post-processor.go +++ b/post-processor/googlecompute-export/post-processor.go @@ -145,7 +145,7 @@ func (p *PostProcessor) PostProcess(ctx context.Context, ui packer.Ui, artifact NetworkProjectId: builderProjectId, StateTimeout: 5 * time.Minute, SourceImageFamily: "debian-9-worker", - SourceImageProjectId: "compute-image-tools", + SourceImageProjectId: []string{"compute-image-tools"}, Subnetwork: p.config.Subnetwork, Zone: p.config.Zone, Scopes: []string{ diff --git a/website/source/partials/builder/googlecompute/_Config-not-required.html.md b/website/source/partials/builder/googlecompute/_Config-not-required.html.md index a9101d361..0fde1419d 100644 --- a/website/source/partials/builder/googlecompute/_Config-not-required.html.md +++ b/website/source/partials/builder/googlecompute/_Config-not-required.html.md @@ -108,7 +108,7 @@ project's default service account unless disable_default_service_account is true. -- `source_image_project_id` (string) - The project ID of the project containing the source image. +- `source_image_project_id` ([]string) - The project ID's of the project containing the source image. - `startup_script_file` (string) - The path to a startup script to run on the VM from which the image will be made. From 3d8bda31a467c5c2ed60556adb0c163e1e609e0d Mon Sep 17 00:00:00 2001 From: Rens Sikma Date: Thu, 20 Feb 2020 12:54:35 +0100 Subject: [PATCH 2/2] modify docstring --- builder/googlecompute/config.go | 3 ++- .../builder/googlecompute/_Config-not-required.html.md | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/builder/googlecompute/config.go b/builder/googlecompute/config.go index b45357f26..cd8bddf2b 100644 --- a/builder/googlecompute/config.go +++ b/builder/googlecompute/config.go @@ -149,7 +149,8 @@ type Config struct { // family always returns its latest image that is not deprecated. Example: // "debian-8". SourceImageFamily string `mapstructure:"source_image_family" required:"true"` - // The project ID's of the project containing the source image. + // A list of project IDs to search for the source image. Packer will search the first + // project ID in the list first, and fall back to the next in the list, until it finds the source image. SourceImageProjectId []string `mapstructure:"source_image_project_id" required:"false"` // The path to a startup script to run on the VM from which the image will // be made. diff --git a/website/source/partials/builder/googlecompute/_Config-not-required.html.md b/website/source/partials/builder/googlecompute/_Config-not-required.html.md index 0fde1419d..41b95f956 100644 --- a/website/source/partials/builder/googlecompute/_Config-not-required.html.md +++ b/website/source/partials/builder/googlecompute/_Config-not-required.html.md @@ -108,7 +108,8 @@ project's default service account unless disable_default_service_account is true. -- `source_image_project_id` ([]string) - The project ID's of the project containing the source image. +- `source_image_project_id` ([]string) - A list of project IDs to search for the source image. Packer will search the first + project ID in the list first, and fall back to the next in the list, until it finds the source image. - `startup_script_file` (string) - The path to a startup script to run on the VM from which the image will be made.