Skip to content

Commit

Permalink
support setting ImageFamily and BootMode when building image
Browse files Browse the repository at this point in the history
  • Loading branch information
hwhuangzsly committed May 25, 2024
1 parent 862227c commit 3c89f8c
Show file tree
Hide file tree
Showing 9 changed files with 195 additions and 5 deletions.
7 changes: 7 additions & 0 deletions .web-docs/components/builder/alicloud-ecs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -301,6 +301,13 @@ builder.
[`dynamic_block`](/packer/docs/templates/hcl_templates/expressions#dynamic-blocks)
will allow you to create those programatically.

- `target_image_family` (string) - The image family of the user-defined image, [2, 128] English or Chinese
characters. It must begin with an uppercase/lowercase letter or a
Chinese character, and may contain numbers, `_` or `-`. It cannot begin
with `aliyun`, `acs:`, `http://` or `https://`.

- `boot_mode` (string) - The boot mode of the user-defined image, it should to be one of 'BIOS', 'UEFI' or 'UEFI-Preferred'.

<!-- End of code generated from the comments of the AlicloudImageConfig struct in builder/ecs/image_config.go; -->


Expand Down
4 changes: 4 additions & 0 deletions builder/ecs/builder.hcl2spec.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

26 changes: 25 additions & 1 deletion builder/ecs/image_config.go
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,13 @@ type AlicloudImageConfig struct {
// will allow you to create those programatically.
AlicloudImageTag config.KeyValues `mapstructure:"tag" required:"false"`
AlicloudDiskDevices `mapstructure:",squash"`
// The image family of the user-defined image, [2, 128] English or Chinese
// characters. It must begin with an uppercase/lowercase letter or a
// Chinese character, and may contain numbers, `_` or `-`. It cannot begin
// with `aliyun`, `acs:`, `http://` or `https://`.
AlicloudTargetImageFamily string `mapstructure:"target_image_family" required:"false"`
// The boot mode of the user-defined image, it should to be one of 'BIOS', 'UEFI' or 'UEFI-Preferred'.
AlicloudBootMode string `mapstructure:"boot_mode" required:"false"`
}

func (c *AlicloudImageConfig) Prepare(ctx *interpolate.Context) []error {
Expand All @@ -178,7 +185,24 @@ func (c *AlicloudImageConfig) Prepare(ctx *interpolate.Context) []error {
if reg.FindString(c.AlicloudImageName) != "" {
errs = append(errs, fmt.Errorf("image_name can't include spaces"))
}

if c.AlicloudTargetImageFamily != "" {
if strings.HasPrefix(c.AlicloudTargetImageFamily, "http://") ||
strings.HasPrefix(c.AlicloudTargetImageFamily, "https://") ||
strings.HasPrefix(c.AlicloudTargetImageFamily, "acs:") ||
strings.HasPrefix(c.AlicloudTargetImageFamily, "aliyun") {
errs = append(errs, fmt.Errorf("target_image_family can't start with 'aliyun', 'acs:', 'http://' or 'https://'"))
} else {
imageFamilyReg := regexp.MustCompile(`^\p{L}[\p{L}_0-9\-\.\:]{1,127}$`)
if !imageFamilyReg.MatchString(c.AlicloudTargetImageFamily) {
errs = append(errs, fmt.Errorf("target_image_family should be [2, 128] English or Chinese characters. It must begin with an uppercase/lowercase letter or a Chinese character, and may contain numbers, '_' or '-'"))
}
}
}
if c.AlicloudBootMode != "" {
if c.AlicloudBootMode != "BIOS" && c.AlicloudBootMode != "UEFI" && c.AlicloudBootMode != "UEFI-Preferred" {
errs = append(errs, fmt.Errorf("boot_mode should to be one of 'BIOS', 'UEFI' or 'UEFI-Preferred'"))
}
}
if len(c.AlicloudImageDestinationRegions) > 0 {
regionSet := make(map[string]struct{})
regions := make([]string, 0, len(c.AlicloudImageDestinationRegions))
Expand Down
92 changes: 92 additions & 0 deletions builder/ecs/image_config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,3 +60,95 @@ func TestECSImageConfigPrepare_imageTags(t *testing.T) {
}, c.AlicloudImageTags)
}
}

func TestECSImageConfigPrepare_targetImageFamily(t *testing.T) {
c := testAlicloudImageConfig()

// 1 character
c.AlicloudTargetImageFamily = "a"
if err := c.Prepare(nil); err == nil {
t.Fatal("should have error")
}

// 129 characters
c.AlicloudTargetImageFamily = "abcdefghijklmnopqrs1abcdefghijklmnopqrs2abcdefghijklmnopqrs3abcdefghijklmnopqrs4abcdefghijklmnopqrs5abcdefghijklmnopqrs6123456789"
if err := c.Prepare(nil); err == nil {
t.Fatal("should have error")
}

// invalid character
c.AlicloudTargetImageFamily = "abc%&"
if err := c.Prepare(nil); err == nil {
t.Fatal("should have error")
}

// begin with invalid character
c.AlicloudTargetImageFamily = ":abc"
if err := c.Prepare(nil); err == nil {
t.Fatal("should have error")
}

// start with acs:
c.AlicloudTargetImageFamily = "acs:"
if err := c.Prepare(nil); err == nil {
t.Fatal("should have error")
}

// start with aliyun
c.AlicloudTargetImageFamily = "aliyun"
if err := c.Prepare(nil); err == nil {
t.Fatal("should have error")
}

// start with http://
c.AlicloudTargetImageFamily = "http://"
if err := c.Prepare(nil); err == nil {
t.Fatal("should have error")
}

// start with https://
c.AlicloudTargetImageFamily = "https://"
if err := c.Prepare(nil); err == nil {
t.Fatal("should have error")
}

// success, begin with Chinese character, and contain :, -, _
c.AlicloudTargetImageFamily = "啊:-_5s是uccess"
if err := c.Prepare(nil); err != nil {
t.Fatalf("shouldn't have err: %s", err)
}

// success, begin with English character
c.AlicloudTargetImageFamily = "a啊:-_5s是uccess"
if err := c.Prepare(nil); err != nil {
t.Fatalf("shouldn't have err: %s", err)
}
}

func TestECSImageConfigPrepare_bootMode(t *testing.T) {
c := testAlicloudImageConfig()

// invalid
c.AlicloudBootMode = "boot"
if err := c.Prepare(nil); err == nil {
t.Fatal("should have error")
}

// UEFI
c.AlicloudBootMode = "UEFI"
if err := c.Prepare(nil); err != nil {
t.Fatalf("shouldn't have err: %s", err)
}

// BIOS
c.AlicloudBootMode = "BIOS"
if err := c.Prepare(nil); err != nil {
t.Fatalf("shouldn't have err: %s", err)
}

// UEFI-Preferred
c.AlicloudBootMode = "UEFI-Preferred"
if err := c.Prepare(nil); err != nil {
t.Fatalf("shouldn't have err: %s", err)
}
}
2 changes: 2 additions & 0 deletions builder/ecs/step_create_image.go
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,8 @@ func (s *stepCreateAlicloudImage) buildCreateImageRequest(state multistep.StateB
request.ImageVersion = config.AlicloudImageVersion
request.Description = config.AlicloudImageDescription
request.ResourceGroupId = config.AlicloudResourceGroupId
request.ImageFamily = config.AlicloudTargetImageFamily
request.BootMode = config.AlicloudBootMode

if s.AlicloudImageIgnoreDataDisks {
snapshotId := state.Get("alicloudsnapshot").(string)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,4 +58,11 @@
[`dynamic_block`](/packer/docs/templates/hcl_templates/expressions#dynamic-blocks)
will allow you to create those programatically.

- `target_image_family` (string) - The image family of the user-defined image, [2, 128] English or Chinese
characters. It must begin with an uppercase/lowercase letter or a
Chinese character, and may contain numbers, `_` or `-`. It cannot begin
with `aliyun`, `acs:`, `http://` or `https://`.

- `boot_mode` (string) - The boot mode of the user-defined image, it should to be one of 'BIOS', 'UEFI' or 'UEFI-Preferred'.

<!-- End of code generated from the comments of the AlicloudImageConfig struct in builder/ecs/image_config.go; -->
9 changes: 5 additions & 4 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ module github.com/hashicorp/packer-plugin-alicloud
go 1.19

require (
github.com/aliyun/alibaba-cloud-sdk-go v1.61.1028
github.com/aliyun/alibaba-cloud-sdk-go v1.62.742
github.com/aliyun/aliyun-oss-go-sdk v2.1.8+incompatible
github.com/hashicorp/hcl/v2 v2.19.1
github.com/hashicorp/packer-plugin-sdk v0.5.2
Expand Down Expand Up @@ -62,7 +62,7 @@ require (
github.com/hashicorp/yamux v0.1.1 // indirect
github.com/jehiah/go-strftime v0.0.0-20171201141054-1d33003b3869 // indirect
github.com/jmespath/go-jmespath v0.4.0 // indirect
github.com/json-iterator/go v1.1.10 // indirect
github.com/json-iterator/go v1.1.12 // indirect
github.com/klauspost/compress v1.11.2 // indirect
github.com/kr/fs v0.1.0 // indirect
github.com/masterzen/simplexml v0.0.0-20190410153822-31eea3082786 // indirect
Expand All @@ -76,8 +76,9 @@ require (
github.com/mitchellh/mapstructure v1.5.0 // indirect
github.com/mitchellh/reflectwalk v1.0.0 // indirect
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.1 // indirect
github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/nu7hatch/gouuid v0.0.0-20131221200532-179d4d0c4d8d // indirect
github.com/opentracing/opentracing-go v1.2.1-0.20220228012449-10b1cf09e00b // indirect
github.com/packer-community/winrmcp v0.0.0-20180921211025-c76d91c1e7db // indirect
github.com/pkg/sftp v1.13.2 // indirect
github.com/ryanuber/go-glob v1.0.0 // indirect
Expand All @@ -100,7 +101,7 @@ require (
google.golang.org/genproto v0.0.0-20221027153422-115e99e71e1c // indirect
google.golang.org/grpc v1.50.1 // indirect
google.golang.org/protobuf v1.28.1 // indirect
gopkg.in/ini.v1 v1.62.0 // indirect
gopkg.in/ini.v1 v1.67.0 // indirect
gopkg.in/yaml.v2 v2.3.0 // indirect
)

Expand Down
Loading

0 comments on commit 3c89f8c

Please sign in to comment.