diff --git a/builder/openstack/run_config.go b/builder/openstack/run_config.go index 0625d264c..f8bc3b514 100644 --- a/builder/openstack/run_config.go +++ b/builder/openstack/run_config.go @@ -252,14 +252,21 @@ func (c *RunConfig) Prepare(ctx *interpolate.Context) []error { } } - hasOnlySourceImage := len(c.SourceImage) > 0 && len(c.SourceImageName) == 0 && len(c.ExternalSourceImageURL) == 0 - hasOnlySourceImageName := len(c.SourceImageName) > 0 && len(c.SourceImage) == 0 && len(c.ExternalSourceImageURL) == 0 - hasOnlyExternalSourceImageURL := len(c.ExternalSourceImageURL) > 0 && len(c.SourceImage) == 0 && len(c.SourceImageName) == 0 - if c.SourceImage == "" && c.SourceImageName == "" && c.ExternalSourceImageURL == "" && c.SourceImageFilters.Filters.Empty() { errs = append(errs, errors.New("Either a source_image, a source_image_name, an external_source_image_url or source_image_filter must be specified")) - } else if !(hasOnlySourceImage || hasOnlySourceImageName || hasOnlyExternalSourceImageURL) { - errs = append(errs, errors.New("Only a source_image, a source_image_name or an external_source_image_url can be specified, not multiple.")) + } else { + // Make sure we've only set one image source option + thereCanBeOnlyOne := []bool{len(c.SourceImageName) > 0, len(c.SourceImage) > 0, len(c.ExternalSourceImageURL) > 0, !c.SourceImageFilters.Filters.Empty()} + numSet := 0 + for _, val := range thereCanBeOnlyOne { + if val { + numSet += 1 + } + } + + if numSet > 1 { + errs = append(errs, errors.New("Only one of the options source_image, source_image_name, external_source_image_url, or source_image_filter can be specified, not multiple.")) + } } // if external_source_image_format is not set use qcow2 as default diff --git a/builder/openstack/run_config_test.go b/builder/openstack/run_config_test.go index dc267076b..70377b217 100644 --- a/builder/openstack/run_config_test.go +++ b/builder/openstack/run_config_test.go @@ -141,6 +141,7 @@ func TestRunConfigPrepare_ExternalSourceImageURL(t *testing.T) { t.Fatalf("err: %s", err) } + c = testRunConfig() // test setting both ExternalSourceImageURL and SourceImageName causes an error c.SourceImage = "" c.SourceImageName = "abcd" @@ -149,6 +150,7 @@ func TestRunConfigPrepare_ExternalSourceImageURL(t *testing.T) { t.Fatalf("err: %s", err) } + c = testRunConfig() // test neither setting SourceImage, SourceImageName or ExternalSourceImageURL causes an error c.SourceImage = "" c.SourceImageName = "" @@ -157,6 +159,7 @@ func TestRunConfigPrepare_ExternalSourceImageURL(t *testing.T) { t.Fatalf("err: %s", err) } + c = testRunConfig() // test setting only ExternalSourceImageURL passes c.SourceImage = "" c.SourceImageName = "" @@ -174,6 +177,27 @@ func TestRunConfigPrepare_ExternalSourceImageURL(t *testing.T) { if matches, _ := regexp.MatchString(p, c.SourceImageName); !matches { t.Fatalf("invalid format for SourceImageName: %s", c.SourceImageName) } + + c = testRunConfig() + // test setting a filter passes + c.SourceImage = "" + c.SourceImageName = "" + c.ExternalSourceImageURL = "" + c.SourceImageFilters = ImageFilter{ + Filters: ImageFilterOptions{ + Name: "Ubuntu 16.04", + Visibility: "public", + Owner: "1234567890", + Tags: []string{"prod", "ready"}, + Properties: map[string]string{"os_distro": "ubuntu", "os_version": "16.04"}, + }, + MostRecent: true, + } + + if err := c.Prepare(nil); len(err) != 0 { + t.Fatalf("Should not error if everything but filter is empty: %s", err) + } + } // This test case confirms that only allowed fields will be set to values