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 }