feature: bsusurrogate, add StepUpdateOMIAttributes step
This commit is contained in:
parent
b46636a39b
commit
2c4b2b8657
|
@ -227,6 +227,11 @@ func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packe
|
|||
OMIDevices: omiDevices,
|
||||
LaunchDevices: launchDevices,
|
||||
},
|
||||
&osccommon.StepUpdateOMIAttributes{
|
||||
AccountIds: b.config.OMIAccountIDs,
|
||||
SnapshotAccountIds: b.config.SnapshotAccountIDs,
|
||||
Ctx: b.config.ctx,
|
||||
},
|
||||
}
|
||||
|
||||
b.runner = common.NewRunner(steps, b.config.PackerConfig, ui)
|
||||
|
|
|
@ -10,25 +10,22 @@ import (
|
|||
|
||||
// OMIConfig is for common configuration related to creating OMIs.
|
||||
type OMIConfig struct {
|
||||
OMIName string `mapstructure:"omi_name"`
|
||||
OMIDescription string `mapstructure:"omi_description"`
|
||||
OMIVirtType string `mapstructure:"omi_virtualization_type"`
|
||||
OMIUsers []string `mapstructure:"omi_users"`
|
||||
OMIGroups []string `mapstructure:"omi_groups"`
|
||||
OMIProductCodes []string `mapstructure:"omi_product_codes"`
|
||||
OMIRegions []string `mapstructure:"omi_regions"`
|
||||
OMISkipRegionValidation bool `mapstructure:"skip_region_validation"`
|
||||
OMITags TagMap `mapstructure:"tags"`
|
||||
OMIENASupport *bool `mapstructure:"ena_support"`
|
||||
OMISriovNetSupport bool `mapstructure:"sriov_support"`
|
||||
OMIForceDeregister bool `mapstructure:"force_deregister"`
|
||||
OMIForceDeleteSnapshot bool `mapstructure:"force_delete_snapshot"`
|
||||
OMIEncryptBootVolume bool `mapstructure:"encrypt_boot"`
|
||||
OMIKmsKeyId string `mapstructure:"kms_key_id"`
|
||||
OMIRegionKMSKeyIDs map[string]string `mapstructure:"region_kms_key_ids"`
|
||||
SnapshotTags TagMap `mapstructure:"snapshot_tags"`
|
||||
SnapshotUsers []string `mapstructure:"snapshot_users"`
|
||||
SnapshotGroups []string `mapstructure:"snapshot_groups"`
|
||||
OMIName string `mapstructure:"omi_name"`
|
||||
OMIDescription string `mapstructure:"omi_description"`
|
||||
OMIVirtType string `mapstructure:"omi_virtualization_type"`
|
||||
OMIAccountIDs []string `mapstructure:"omi_account_ids"`
|
||||
OMIGroups []string `mapstructure:"omi_groups"`
|
||||
OMIProductCodes []string `mapstructure:"omi_product_codes"`
|
||||
OMIRegions []string `mapstructure:"omi_regions"`
|
||||
OMISkipRegionValidation bool `mapstructure:"skip_region_validation"`
|
||||
OMITags TagMap `mapstructure:"tags"`
|
||||
OMIENASupport *bool `mapstructure:"ena_support"`
|
||||
OMISriovNetSupport bool `mapstructure:"sriov_support"`
|
||||
OMIForceDeregister bool `mapstructure:"force_deregister"`
|
||||
OMIForceDeleteSnapshot bool `mapstructure:"force_delete_snapshot"`
|
||||
SnapshotTags TagMap `mapstructure:"snapshot_tags"`
|
||||
SnapshotAccountIDs []string `mapstructure:"snapshot_account_ids"`
|
||||
SnapshotGroups []string `mapstructure:"snapshot_groups"`
|
||||
}
|
||||
|
||||
func stringInSlice(s []string, searchstr string) bool {
|
||||
|
@ -47,52 +44,8 @@ func (c *OMIConfig) Prepare(accessConfig *AccessConfig, ctx *interpolate.Context
|
|||
errs = append(errs, fmt.Errorf("omi_name must be specified"))
|
||||
}
|
||||
|
||||
// Make sure that if we have region_kms_key_ids defined,
|
||||
// the regions in region_kms_key_ids are also in omi_regions
|
||||
if len(c.OMIRegionKMSKeyIDs) > 0 {
|
||||
for kmsKeyRegion := range c.OMIRegionKMSKeyIDs {
|
||||
if !stringInSlice(c.OMIRegions, kmsKeyRegion) {
|
||||
errs = append(errs, fmt.Errorf("Region %s is in region_kms_key_ids but not in omi_regions", kmsKeyRegion))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
errs = append(errs, c.prepareRegions(accessConfig)...)
|
||||
|
||||
if len(c.OMIUsers) > 0 && c.OMIEncryptBootVolume {
|
||||
errs = append(errs, fmt.Errorf("Cannot share OMI with encrypted boot volume"))
|
||||
}
|
||||
|
||||
var kmsKeys []string
|
||||
if len(c.OMIKmsKeyId) > 0 {
|
||||
kmsKeys = append(kmsKeys, c.OMIKmsKeyId)
|
||||
}
|
||||
if len(c.OMIRegionKMSKeyIDs) > 0 {
|
||||
for _, kmsKey := range c.OMIRegionKMSKeyIDs {
|
||||
if len(kmsKey) == 0 {
|
||||
kmsKeys = append(kmsKeys, c.OMIKmsKeyId)
|
||||
}
|
||||
}
|
||||
}
|
||||
for _, kmsKey := range kmsKeys {
|
||||
if !validateKmsKey(kmsKey) {
|
||||
errs = append(errs, fmt.Errorf("%s is not a valid KMS Key Id.", kmsKey))
|
||||
}
|
||||
}
|
||||
|
||||
if len(c.SnapshotUsers) > 0 {
|
||||
if len(c.OMIKmsKeyId) == 0 && c.OMIEncryptBootVolume {
|
||||
errs = append(errs, fmt.Errorf("Cannot share snapshot encrypted with default KMS key"))
|
||||
}
|
||||
if len(c.OMIRegionKMSKeyIDs) > 0 {
|
||||
for _, kmsKey := range c.OMIRegionKMSKeyIDs {
|
||||
if len(kmsKey) == 0 {
|
||||
errs = append(errs, fmt.Errorf("Cannot share snapshot encrypted with default KMS key"))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if len(c.OMIName) < 3 || len(c.OMIName) > 128 {
|
||||
errs = append(errs, fmt.Errorf("omi_name must be between 3 and 128 characters long"))
|
||||
}
|
||||
|
@ -126,13 +79,6 @@ func (c *OMIConfig) prepareRegions(accessConfig *AccessConfig) (errs []error) {
|
|||
// Mark that we saw the region
|
||||
regionSet[region] = struct{}{}
|
||||
|
||||
// Make sure that if we have region_kms_key_ids defined,
|
||||
// the regions in omi_regions are also in region_kms_key_ids
|
||||
if len(c.OMIRegionKMSKeyIDs) > 0 {
|
||||
if _, ok := c.OMIRegionKMSKeyIDs[region]; !ok {
|
||||
errs = append(errs, fmt.Errorf("Region %s is in omi_regions but not in region_kms_key_ids", region))
|
||||
}
|
||||
}
|
||||
if (accessConfig != nil) && (region == accessConfig.RawRegion) {
|
||||
// make sure we don't try to copy to the region we originally
|
||||
// create the OMI in.
|
||||
|
|
|
@ -68,64 +68,35 @@ func TestOMIConfigPrepare_regions(t *testing.T) {
|
|||
}
|
||||
|
||||
c.OMIRegions = []string{"us-east-1", "us-east-2", "us-west-1"}
|
||||
c.OMIRegionKMSKeyIDs = map[string]string{
|
||||
"us-east-1": "123-456-7890",
|
||||
"us-west-1": "789-012-3456",
|
||||
"us-east-2": "456-789-0123",
|
||||
}
|
||||
|
||||
if errs = c.prepareRegions(accessConf); len(errs) > 0 {
|
||||
t.Fatal(fmt.Sprintf("shouldn't have error: %s", errs[0]))
|
||||
}
|
||||
|
||||
c.OMIRegions = []string{"us-east-1", "us-east-2", "us-west-1"}
|
||||
c.OMIRegionKMSKeyIDs = map[string]string{
|
||||
"us-east-1": "123-456-7890",
|
||||
"us-west-1": "789-012-3456",
|
||||
"us-east-2": "",
|
||||
}
|
||||
|
||||
if errs = c.prepareRegions(accessConf); len(errs) > 0 {
|
||||
t.Fatal("should have passed; we are able to use default KMS key if not sharing")
|
||||
}
|
||||
|
||||
c.SnapshotUsers = []string{"user-foo", "user-bar"}
|
||||
c.SnapshotAccountIDs = []string{"user-foo", "user-bar"}
|
||||
c.OMIRegions = []string{"us-east-1", "us-east-2", "us-west-1"}
|
||||
c.OMIRegionKMSKeyIDs = map[string]string{
|
||||
"us-east-1": "123-456-7890",
|
||||
"us-west-1": "789-012-3456",
|
||||
"us-east-2": "",
|
||||
}
|
||||
|
||||
if errs = c.prepareRegions(accessConf); len(errs) > 0 {
|
||||
t.Fatal("should have an error b/c can't use default KMS key if sharing")
|
||||
}
|
||||
|
||||
c.OMIRegions = []string{"us-east-1", "us-west-1"}
|
||||
c.OMIRegionKMSKeyIDs = map[string]string{
|
||||
"us-east-1": "123-456-7890",
|
||||
"us-west-1": "789-012-3456",
|
||||
"us-east-2": "456-789-0123",
|
||||
}
|
||||
|
||||
if errs = c.prepareRegions(accessConf); len(errs) > 0 {
|
||||
t.Fatal("should have error b/c theres a region in the key map that isn't in omi_regions")
|
||||
}
|
||||
|
||||
c.OMIRegions = []string{"us-east-1", "us-west-1", "us-east-2"}
|
||||
c.OMIRegionKMSKeyIDs = map[string]string{
|
||||
"us-east-1": "123-456-7890",
|
||||
"us-west-1": "789-012-3456",
|
||||
}
|
||||
|
||||
if err := c.Prepare(accessConf, nil); err == nil {
|
||||
t.Fatal("should have error b/c theres a region in in omi_regions that isn't in the key map")
|
||||
}
|
||||
|
||||
c.SnapshotUsers = []string{"foo", "bar"}
|
||||
c.OMIKmsKeyId = "123-abc-456"
|
||||
c.OMIEncryptBootVolume = true
|
||||
c.SnapshotAccountIDs = []string{"foo", "bar"}
|
||||
c.OMIRegions = []string{"us-east-1", "us-west-1"}
|
||||
c.OMIRegionKMSKeyIDs = map[string]string{
|
||||
"us-east-1": "123-456-7890",
|
||||
"us-west-1": "",
|
||||
}
|
||||
|
||||
if errs = c.prepareRegions(accessConf); len(errs) > 0 {
|
||||
t.Fatal("should have error b/c theres a region in in omi_regions that isn't in the key map")
|
||||
}
|
||||
|
@ -133,66 +104,13 @@ func TestOMIConfigPrepare_regions(t *testing.T) {
|
|||
// allow rawregion to exist in omi_regions list.
|
||||
accessConf = getFakeAccessConfig("us-east-1")
|
||||
c.OMIRegions = []string{"us-east-1", "us-west-1", "us-east-2"}
|
||||
c.OMIRegionKMSKeyIDs = nil
|
||||
|
||||
if errs = c.prepareRegions(accessConf); len(errs) > 0 {
|
||||
t.Fatal("should allow user to have the raw region in omi_regions")
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func TestOMIConfigPrepare_Share_EncryptedBoot(t *testing.T) {
|
||||
c := testOMIConfig()
|
||||
c.OMIUsers = []string{"testAccountID"}
|
||||
c.OMIEncryptBootVolume = true
|
||||
|
||||
accessConf := testAccessConfig()
|
||||
|
||||
c.OMIKmsKeyId = ""
|
||||
if err := c.Prepare(accessConf, nil); err == nil {
|
||||
t.Fatal("shouldn't be able to share omi with encrypted boot volume")
|
||||
}
|
||||
|
||||
c.OMIKmsKeyId = "89c3fb9a-de87-4f2a-aedc-fddc5138193c"
|
||||
if err := c.Prepare(accessConf, nil); err == nil {
|
||||
t.Fatal("shouldn't be able to share omi with encrypted boot volume")
|
||||
}
|
||||
}
|
||||
|
||||
func TestOMIConfigPrepare_ValidateKmsKey(t *testing.T) {
|
||||
c := testOMIConfig()
|
||||
c.OMIEncryptBootVolume = true
|
||||
|
||||
accessConf := testAccessConfig()
|
||||
|
||||
validCases := []string{
|
||||
"abcd1234-e567-890f-a12b-a123b4cd56ef",
|
||||
"alias/foo/bar",
|
||||
"arn:aws:kms:us-east-1:012345678910:key/abcd1234-a123-456a-a12b-a123b4cd56ef",
|
||||
"arn:aws:kms:us-east-1:012345678910:alias/foo/bar",
|
||||
}
|
||||
for _, validCase := range validCases {
|
||||
c.OMIKmsKeyId = validCase
|
||||
if err := c.Prepare(accessConf, nil); err != nil {
|
||||
t.Fatalf("%s should not have failed KMS key validation", validCase)
|
||||
}
|
||||
}
|
||||
|
||||
invalidCases := []string{
|
||||
"ABCD1234-e567-890f-a12b-a123b4cd56ef",
|
||||
"ghij1234-e567-890f-a12b-a123b4cd56ef",
|
||||
"ghij1234+e567_890f-a12b-a123b4cd56ef",
|
||||
"foo/bar",
|
||||
"arn:aws:kms:us-east-1:012345678910:foo/bar",
|
||||
}
|
||||
for _, invalidCase := range invalidCases {
|
||||
c.OMIKmsKeyId = invalidCase
|
||||
if err := c.Prepare(accessConf, nil); err == nil {
|
||||
t.Fatalf("%s should have failed KMS key validation", invalidCase)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func TestOMINameValidation(t *testing.T) {
|
||||
c := testOMIConfig()
|
||||
|
||||
|
|
|
@ -0,0 +1,125 @@
|
|||
package common
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/tls"
|
||||
"fmt"
|
||||
"net/http"
|
||||
|
||||
"github.com/hashicorp/packer/helper/multistep"
|
||||
"github.com/hashicorp/packer/packer"
|
||||
"github.com/hashicorp/packer/template/interpolate"
|
||||
"github.com/outscale/osc-go/oapi"
|
||||
)
|
||||
|
||||
type StepUpdateOMIAttributes struct {
|
||||
AccountIds []string
|
||||
SnapshotAccountIds []string
|
||||
Ctx interpolate.Context
|
||||
}
|
||||
|
||||
func (s *StepUpdateOMIAttributes) Run(_ context.Context, state multistep.StateBag) multistep.StepAction {
|
||||
oapiconn := state.Get("oapi").(*oapi.Client)
|
||||
config := state.Get("config").(*oapi.Config)
|
||||
ui := state.Get("ui").(packer.Ui)
|
||||
omis := state.Get("omis").(map[string]string)
|
||||
snapshots := state.Get("snapshots").(map[string][]string)
|
||||
|
||||
// Determine if there is any work to do.
|
||||
valid := false
|
||||
valid = valid || (s.AccountIds != nil && len(s.AccountIds) > 0)
|
||||
valid = valid || (s.SnapshotAccountIds != nil && len(s.SnapshotAccountIds) > 0)
|
||||
|
||||
if !valid {
|
||||
return multistep.ActionContinue
|
||||
}
|
||||
|
||||
s.Ctx.Data = extractBuildInfo(oapiconn.GetConfig().Region, state)
|
||||
|
||||
updateSnapshoptRequest := oapi.UpdateSnapshotRequest{
|
||||
PermissionsToCreateVolume: oapi.PermissionsOnResourceCreation{
|
||||
Additions: oapi.PermissionsOnResource{
|
||||
AccountIds: s.AccountIds,
|
||||
GlobalPermission: true,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
updateImageRequest := oapi.UpdateImageRequest{
|
||||
PermissionsToLaunch: oapi.PermissionsOnResourceCreation{
|
||||
Additions: oapi.PermissionsOnResource{
|
||||
AccountIds: s.AccountIds,
|
||||
GlobalPermission: true,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
// Updating image attributes
|
||||
for region, omi := range omis {
|
||||
ui.Say(fmt.Sprintf("Updating attributes on OMI (%s)...", omi))
|
||||
newConfig := &oapi.Config{
|
||||
UserAgent: config.UserAgent,
|
||||
SecretKey: config.SecretKey,
|
||||
Service: config.Service,
|
||||
Region: region, //New region
|
||||
URL: config.URL,
|
||||
}
|
||||
|
||||
skipClient := &http.Client{
|
||||
Transport: &http.Transport{
|
||||
TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
|
||||
},
|
||||
}
|
||||
|
||||
regionconn := oapi.NewClient(newConfig, skipClient)
|
||||
|
||||
ui.Message(fmt.Sprintf("Updating: %s", omi))
|
||||
updateImageRequest.ImageId = omi
|
||||
_, err := regionconn.POST_UpdateImage(updateImageRequest)
|
||||
if err != nil {
|
||||
err := fmt.Errorf("Error updating OMI: %s", err)
|
||||
state.Put("error", err)
|
||||
ui.Error(err.Error())
|
||||
return multistep.ActionHalt
|
||||
}
|
||||
}
|
||||
|
||||
// Updating snapshot attributes
|
||||
for region, region_snapshots := range snapshots {
|
||||
for _, snapshot := range region_snapshots {
|
||||
ui.Say(fmt.Sprintf("Updating attributes on snapshot (%s)...", snapshot))
|
||||
newConfig := &oapi.Config{
|
||||
UserAgent: config.UserAgent,
|
||||
SecretKey: config.SecretKey,
|
||||
Service: config.Service,
|
||||
Region: region, //New region
|
||||
URL: config.URL,
|
||||
}
|
||||
|
||||
skipClient := &http.Client{
|
||||
Transport: &http.Transport{
|
||||
TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
|
||||
},
|
||||
}
|
||||
|
||||
regionconn := oapi.NewClient(newConfig, skipClient)
|
||||
|
||||
ui.Message(fmt.Sprintf("Updating: %s", snapshot))
|
||||
updateSnapshoptRequest.SnapshotId = snapshot
|
||||
_, err := regionconn.POST_UpdateSnapshot(updateSnapshoptRequest)
|
||||
if err != nil {
|
||||
err := fmt.Errorf("Error updating snapshot: %s", err)
|
||||
state.Put("error", err)
|
||||
ui.Error(err.Error())
|
||||
return multistep.ActionHalt
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
return multistep.ActionContinue
|
||||
}
|
||||
|
||||
func (s *StepUpdateOMIAttributes) Cleanup(state multistep.StateBag) {
|
||||
// No cleanup...
|
||||
}
|
Loading…
Reference in New Issue