package common import ( "fmt" "net/url" "os" "github.com/hashicorp/packer/template/interpolate" "github.com/hashicorp/packer/version" "github.com/ucloud/ucloud-sdk-go/services/uaccount" "github.com/ucloud/ucloud-sdk-go/services/ufile" "github.com/ucloud/ucloud-sdk-go/services/uhost" "github.com/ucloud/ucloud-sdk-go/services/unet" "github.com/ucloud/ucloud-sdk-go/services/vpc" "github.com/ucloud/ucloud-sdk-go/ucloud" "github.com/ucloud/ucloud-sdk-go/ucloud/auth" ) type AccessConfig struct { PublicKey string `mapstructure:"public_key"` PrivateKey string `mapstructure:"private_key"` Region string `mapstructure:"region"` ProjectId string `mapstructure:"project_id"` BaseUrl string `mapstructure:"base_url"` client *UCloudClient } func (c *AccessConfig) Client() (*UCloudClient, error) { if c.client != nil { return c.client, nil } cfg := ucloud.NewConfig() cfg.Region = c.Region cfg.ProjectId = c.ProjectId if c.BaseUrl != "" { cfg.BaseUrl = c.BaseUrl } cfg.UserAgent = fmt.Sprintf("Packer-UCloud/%s", version.FormattedVersion()) // set default max retry count cfg.MaxRetries = 3 cred := auth.NewCredential() cred.PublicKey = c.PublicKey cred.PrivateKey = c.PrivateKey c.client = &UCloudClient{} c.client.UHostConn = uhost.NewClient(&cfg, &cred) c.client.UNetConn = unet.NewClient(&cfg, &cred) c.client.VPCConn = vpc.NewClient(&cfg, &cred) c.client.UAccountConn = uaccount.NewClient(&cfg, &cred) c.client.UFileConn = ufile.NewClient(&cfg, &cred) return c.client, nil } func (c *AccessConfig) Prepare(ctx *interpolate.Context) []error { var errs []error if err := c.Config(); err != nil { errs = append(errs, err) } if c.Region == "" { c.Region = os.Getenv("UCLOUD_REGION") } if c.Region == "" { errs = append(errs, fmt.Errorf("%q must be set", "region")) } if c.BaseUrl != "" { if _, err := url.Parse(c.BaseUrl); err != nil { errs = append(errs, fmt.Errorf("%q is invalid, should be an valid ucloud base_url, got %q, parse error: %s", "base_url", c.BaseUrl, err)) } } if len(errs) > 0 { return errs } return nil } func (c *AccessConfig) Config() error { if c.PublicKey == "" { c.PublicKey = os.Getenv("UCLOUD_PUBLIC_KEY") } if c.PrivateKey == "" { c.PrivateKey = os.Getenv("UCLOUD_PRIVATE_KEY") } if c.ProjectId == "" { c.ProjectId = os.Getenv("UCLOUD_PROJECT_ID") } if c.PublicKey == "" || c.PrivateKey == "" || c.ProjectId == "" { return fmt.Errorf("%q, %q, and %q must be set", "public_key", "private_key", "project_id") } return nil } func (c *AccessConfig) ValidateProjectId(projectId string) error { supportedProjectIds, err := c.getSupportedProjectIds() if err != nil { return err } for _, supportedProjectId := range supportedProjectIds { if projectId == supportedProjectId { return nil } } return fmt.Errorf("%q is invalid, should be an valid ucloud project_id, got %q", "project_id", projectId) } func (c *AccessConfig) ValidateRegion(region string) error { supportedRegions, err := c.getSupportedRegions() if err != nil { return err } for _, supportedRegion := range supportedRegions { if region == supportedRegion { return nil } } return fmt.Errorf("%q is invalid, should be an valid ucloud region, got %q", "region", region) } func (c *AccessConfig) ValidateZone(region, zone string) error { supportedZones, err := c.getSupportedZones(region) if err != nil { return err } for _, supportedZone := range supportedZones { if zone == supportedZone { return nil } } return fmt.Errorf("%q is invalid, should be an valid ucloud zone, got %q", "availability_zone", zone) } func (c *AccessConfig) getSupportedProjectIds() ([]string, error) { client, err := c.Client() conn := client.UAccountConn if err != nil { return nil, err } req := conn.NewGetProjectListRequest() resp, err := conn.GetProjectList(req) if err != nil { return nil, err } validProjectIds := make([]string, len(resp.ProjectSet)) for _, val := range resp.ProjectSet { if !IsStringIn(val.ProjectId, validProjectIds) { validProjectIds = append(validProjectIds, val.ProjectId) } } return validProjectIds, nil } func (c *AccessConfig) getSupportedRegions() ([]string, error) { client, err := c.Client() conn := client.UAccountConn if err != nil { return nil, err } req := conn.NewGetRegionRequest() resp, err := conn.GetRegion(req) if err != nil { return nil, err } validRegions := make([]string, len(resp.Regions)) for _, val := range resp.Regions { if !IsStringIn(val.Region, validRegions) { validRegions = append(validRegions, val.Region) } } return validRegions, nil } func (c *AccessConfig) getSupportedZones(region string) ([]string, error) { client, err := c.Client() conn := client.UAccountConn if err != nil { return nil, err } req := conn.NewGetRegionRequest() resp, err := conn.GetRegion(req) if err != nil { return nil, err } validZones := make([]string, len(resp.Regions)) for _, val := range resp.Regions { if val.Region == region && !IsStringIn(val.Zone, validZones) { validZones = append(validZones, val.Zone) } } return validZones, nil }