github.phpd.cn/hashicorp/packer@v1.3.2/builder/amazon/common/step_modify_ami_attributes.go (about)

     1  package common
     2  
     3  import (
     4  	"context"
     5  	"fmt"
     6  
     7  	"github.com/aws/aws-sdk-go/aws"
     8  	"github.com/aws/aws-sdk-go/aws/session"
     9  	"github.com/aws/aws-sdk-go/service/ec2"
    10  	"github.com/hashicorp/packer/helper/multistep"
    11  	"github.com/hashicorp/packer/packer"
    12  	"github.com/hashicorp/packer/template/interpolate"
    13  )
    14  
    15  type StepModifyAMIAttributes struct {
    16  	Users          []string
    17  	Groups         []string
    18  	SnapshotUsers  []string
    19  	SnapshotGroups []string
    20  	ProductCodes   []string
    21  	Description    string
    22  	Ctx            interpolate.Context
    23  }
    24  
    25  func (s *StepModifyAMIAttributes) Run(_ context.Context, state multistep.StateBag) multistep.StepAction {
    26  	ec2conn := state.Get("ec2").(*ec2.EC2)
    27  	session := state.Get("awsSession").(*session.Session)
    28  	ui := state.Get("ui").(packer.Ui)
    29  	amis := state.Get("amis").(map[string]string)
    30  	snapshots := state.Get("snapshots").(map[string][]string)
    31  
    32  	// Determine if there is any work to do.
    33  	valid := false
    34  	valid = valid || s.Description != ""
    35  	valid = valid || (s.Users != nil && len(s.Users) > 0)
    36  	valid = valid || (s.Groups != nil && len(s.Groups) > 0)
    37  	valid = valid || (s.ProductCodes != nil && len(s.ProductCodes) > 0)
    38  	valid = valid || (s.SnapshotUsers != nil && len(s.SnapshotUsers) > 0)
    39  	valid = valid || (s.SnapshotGroups != nil && len(s.SnapshotGroups) > 0)
    40  
    41  	if !valid {
    42  		return multistep.ActionContinue
    43  	}
    44  
    45  	var err error
    46  	s.Ctx.Data = extractBuildInfo(*ec2conn.Config.Region, state)
    47  	s.Description, err = interpolate.Render(s.Description, &s.Ctx)
    48  	if err != nil {
    49  		err = fmt.Errorf("Error interpolating AMI description: %s", err)
    50  		ui.Error(err.Error())
    51  		return multistep.ActionHalt
    52  	}
    53  
    54  	// Construct the modify image and snapshot attribute requests we're going
    55  	// to make. We need to make each separately since the EC2 API only allows
    56  	// changing one type at a kind currently.
    57  	options := make(map[string]*ec2.ModifyImageAttributeInput)
    58  	if s.Description != "" {
    59  		options["description"] = &ec2.ModifyImageAttributeInput{
    60  			Description: &ec2.AttributeValue{Value: &s.Description},
    61  		}
    62  	}
    63  	snapshotOptions := make(map[string]*ec2.ModifySnapshotAttributeInput)
    64  
    65  	if len(s.Groups) > 0 {
    66  		groups := make([]*string, len(s.Groups))
    67  		addsImage := make([]*ec2.LaunchPermission, len(s.Groups))
    68  		addGroups := &ec2.ModifyImageAttributeInput{
    69  			LaunchPermission: &ec2.LaunchPermissionModifications{},
    70  		}
    71  
    72  		for i, g := range s.Groups {
    73  			groups[i] = aws.String(g)
    74  			addsImage[i] = &ec2.LaunchPermission{
    75  				Group: aws.String(g),
    76  			}
    77  		}
    78  
    79  		addGroups.UserGroups = groups
    80  		addGroups.LaunchPermission.Add = addsImage
    81  		options["groups"] = addGroups
    82  	}
    83  
    84  	if len(s.SnapshotGroups) > 0 {
    85  		groups := make([]*string, len(s.SnapshotGroups))
    86  		addsSnapshot := make([]*ec2.CreateVolumePermission, len(s.SnapshotGroups))
    87  		addSnapshotGroups := &ec2.ModifySnapshotAttributeInput{
    88  			CreateVolumePermission: &ec2.CreateVolumePermissionModifications{},
    89  		}
    90  
    91  		for i, g := range s.SnapshotGroups {
    92  			groups[i] = aws.String(g)
    93  			addsSnapshot[i] = &ec2.CreateVolumePermission{
    94  				Group: aws.String(g),
    95  			}
    96  		}
    97  		addSnapshotGroups.GroupNames = groups
    98  		addSnapshotGroups.CreateVolumePermission.Add = addsSnapshot
    99  		snapshotOptions["groups"] = addSnapshotGroups
   100  	}
   101  
   102  	if len(s.Users) > 0 {
   103  		users := make([]*string, len(s.Users))
   104  		addsImage := make([]*ec2.LaunchPermission, len(s.Users))
   105  		for i, u := range s.Users {
   106  			users[i] = aws.String(u)
   107  			addsImage[i] = &ec2.LaunchPermission{UserId: aws.String(u)}
   108  		}
   109  
   110  		options["users"] = &ec2.ModifyImageAttributeInput{
   111  			UserIds: users,
   112  			LaunchPermission: &ec2.LaunchPermissionModifications{
   113  				Add: addsImage,
   114  			},
   115  		}
   116  	}
   117  
   118  	if len(s.SnapshotUsers) > 0 {
   119  		users := make([]*string, len(s.SnapshotUsers))
   120  		addsSnapshot := make([]*ec2.CreateVolumePermission, len(s.SnapshotUsers))
   121  		for i, u := range s.SnapshotUsers {
   122  			users[i] = aws.String(u)
   123  			addsSnapshot[i] = &ec2.CreateVolumePermission{UserId: aws.String(u)}
   124  		}
   125  
   126  		snapshotOptions["users"] = &ec2.ModifySnapshotAttributeInput{
   127  			UserIds: users,
   128  			CreateVolumePermission: &ec2.CreateVolumePermissionModifications{
   129  				Add: addsSnapshot,
   130  			},
   131  		}
   132  	}
   133  
   134  	if len(s.ProductCodes) > 0 {
   135  		codes := make([]*string, len(s.ProductCodes))
   136  		for i, c := range s.ProductCodes {
   137  			codes[i] = &c
   138  		}
   139  		options["product codes"] = &ec2.ModifyImageAttributeInput{
   140  			ProductCodes: codes,
   141  		}
   142  	}
   143  
   144  	// Modifying image attributes
   145  	for region, ami := range amis {
   146  		ui.Say(fmt.Sprintf("Modifying attributes on AMI (%s)...", ami))
   147  		regionConn := ec2.New(session, &aws.Config{
   148  			Region: aws.String(region),
   149  		})
   150  		for name, input := range options {
   151  			ui.Message(fmt.Sprintf("Modifying: %s", name))
   152  			input.ImageId = &ami
   153  			_, err := regionConn.ModifyImageAttribute(input)
   154  			if err != nil {
   155  				err := fmt.Errorf("Error modify AMI attributes: %s", err)
   156  				state.Put("error", err)
   157  				ui.Error(err.Error())
   158  				return multistep.ActionHalt
   159  			}
   160  		}
   161  	}
   162  
   163  	// Modifying snapshot attributes
   164  	for region, region_snapshots := range snapshots {
   165  		for _, snapshot := range region_snapshots {
   166  			ui.Say(fmt.Sprintf("Modifying attributes on snapshot (%s)...", snapshot))
   167  			regionConn := ec2.New(session, &aws.Config{
   168  				Region: aws.String(region),
   169  			})
   170  			for name, input := range snapshotOptions {
   171  				ui.Message(fmt.Sprintf("Modifying: %s", name))
   172  				input.SnapshotId = &snapshot
   173  				_, err := regionConn.ModifySnapshotAttribute(input)
   174  				if err != nil {
   175  					err := fmt.Errorf("Error modify snapshot attributes: %s", err)
   176  					state.Put("error", err)
   177  					ui.Error(err.Error())
   178  					return multistep.ActionHalt
   179  				}
   180  			}
   181  		}
   182  	}
   183  
   184  	return multistep.ActionContinue
   185  }
   186  
   187  func (s *StepModifyAMIAttributes) Cleanup(state multistep.StateBag) {
   188  	// No cleanup...
   189  }