diff --git a/.web-docs/components/builder/linode/README.md b/.web-docs/components/builder/linode/README.md index 3ce0501..2654932 100644 --- a/.web-docs/components/builder/linode/README.md +++ b/.web-docs/components/builder/linode/README.md @@ -123,6 +123,8 @@ can also be supplied to override the typical auto-generated key: - `firewall_id` (int) - The ID of the Firewall to attach this Linode to upon creation. +- `image_regions` ([]string) - The regions where the outcome image will be replicated to. + diff --git a/builder/linode/config.go b/builder/linode/config.go index f1ab4e0..6670dff 100644 --- a/builder/linode/config.go +++ b/builder/linode/config.go @@ -152,6 +152,9 @@ type Config struct { // The ID of the Firewall to attach this Linode to upon creation. FirewallID int `mapstructure:"firewall_id" required:"false"` + + // The regions where the outcome image will be replicated to. + ImageRegions []string `mapstructure:"image_regions" required:"false"` } func createRandomRootPassword() (string, error) { diff --git a/builder/linode/config.hcl2spec.go b/builder/linode/config.hcl2spec.go index 98093c6..f0e4dca 100644 --- a/builder/linode/config.hcl2spec.go +++ b/builder/linode/config.hcl2spec.go @@ -89,6 +89,7 @@ type FlatConfig struct { CloudInit *bool `mapstructure:"cloud_init" required:"false" cty:"cloud_init" hcl:"cloud_init"` Metadata *FlatMetadata `mapstructure:"metadata" required:"false" cty:"metadata" hcl:"metadata"` FirewallID *int `mapstructure:"firewall_id" required:"false" cty:"firewall_id" hcl:"firewall_id"` + ImageRegions []string `mapstructure:"image_regions" required:"false" cty:"image_regions" hcl:"image_regions"` } // FlatMapstructure returns a new FlatConfig. @@ -182,6 +183,7 @@ func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec { "cloud_init": &hcldec.AttrSpec{Name: "cloud_init", Type: cty.Bool, Required: false}, "metadata": &hcldec.BlockSpec{TypeName: "metadata", Nested: hcldec.ObjectSpec((*FlatMetadata)(nil).HCL2Spec())}, "firewall_id": &hcldec.AttrSpec{Name: "firewall_id", Type: cty.Number, Required: false}, + "image_regions": &hcldec.AttrSpec{Name: "image_regions", Type: cty.List(cty.String), Required: false}, } return s } diff --git a/builder/linode/config_test.go b/builder/linode/config_test.go index 75099ed..2fc6063 100644 --- a/builder/linode/config_test.go +++ b/builder/linode/config_test.go @@ -24,7 +24,8 @@ func TestPrepare(t *testing.T) { Region: "us-ord", InstanceType: "g6-standard-1", - Image: "linode/debian10", + Image: "linode/debian12", + ImageRegions: []string{"us-ord", "us-mia", "us-lax"}, } warnings, err := config.Prepare() diff --git a/builder/linode/step_create_image.go b/builder/linode/step_create_image.go index ed7a2b7..3c7f277 100644 --- a/builder/linode/step_create_image.go +++ b/builder/linode/step_create_image.go @@ -45,6 +45,22 @@ func (s *stepCreateImage) Run(ctx context.Context, state multistep.StateBag) mul return handleError("Failed to wait for image creation", err) } + if len(c.ImageRegions) > 0 { + image, err = s.client.ReplicateImage(ctx, image.ID, linodego.ImageReplicateOptions{ + Regions: c.ImageRegions, + }) + if err != nil { + return handleError("Failed to replicate the image", err) + } + + for _, r := range c.ImageRegions { + _, err = s.client.WaitForImageRegionStatus(ctx, image.ID, r, linodego.ImageRegionStatusAvailable) + if err != nil { + return handleError("Failed to wait for the image replication", err) + } + } + } + image, err = s.client.GetImage(ctx, image.ID) if err != nil { return handleError("Failed to get image", err)