Merge pull request #8247 from b-b3rn4rd/master
New Feature: allow to specify IAM policy for a temporary instance profile
This commit is contained in:
commit
cdc3fdf926
|
@ -45,6 +45,15 @@ type VpcFilterOptions struct {
|
|||
Filters map[*string]*string
|
||||
}
|
||||
|
||||
type PolicyDocument struct {
|
||||
Version string
|
||||
Statement []struct {
|
||||
Effect string
|
||||
Action []string
|
||||
Resource string
|
||||
}
|
||||
}
|
||||
|
||||
func (d *VpcFilterOptions) Empty() bool {
|
||||
return len(d.Filters) == 0
|
||||
}
|
||||
|
@ -124,6 +133,25 @@ type RunConfig struct {
|
|||
// profile](https://docs.aws.amazon.com/IAM/latest/UserGuide/instance-profiles.html)
|
||||
// to launch the EC2 instance with.
|
||||
IamInstanceProfile string `mapstructure:"iam_instance_profile" required:"false"`
|
||||
// Temporary IAM instance profile policy document
|
||||
// If IamInstanceProfile is specified it will be used instead. Example:
|
||||
//
|
||||
// ```json
|
||||
//{
|
||||
// "Version": "2012-10-17",
|
||||
// "Statement": [
|
||||
// {
|
||||
// "Action": [
|
||||
// "logs:*"
|
||||
// ],
|
||||
// "Effect": "Allow",
|
||||
// "Resource": "*"
|
||||
// }
|
||||
// ]
|
||||
//}
|
||||
// ```
|
||||
//
|
||||
TemporaryIamInstanceProfilePolicyDocument *PolicyDocument `mapstructure:"temporary_iam_instance_profile_policy_document" required:"false"`
|
||||
// Automatically terminate instances on
|
||||
// shutdown in case Packer exits ungracefully. Possible values are stop and
|
||||
// terminate. Defaults to stop.
|
||||
|
|
|
@ -0,0 +1,194 @@
|
|||
package common
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"github.com/aws/aws-sdk-go/aws"
|
||||
"log"
|
||||
"time"
|
||||
|
||||
"encoding/json"
|
||||
"github.com/aws/aws-sdk-go/service/iam"
|
||||
"github.com/hashicorp/packer/common/uuid"
|
||||
"github.com/hashicorp/packer/helper/multistep"
|
||||
"github.com/hashicorp/packer/packer"
|
||||
)
|
||||
|
||||
type StepIamInstanceProfile struct {
|
||||
IamInstanceProfile string
|
||||
TemporaryIamInstanceProfilePolicyDocument *PolicyDocument
|
||||
createdInstanceProfileName string
|
||||
createdRoleName string
|
||||
createdPolicyName string
|
||||
roleIsAttached bool
|
||||
}
|
||||
|
||||
func (s *StepIamInstanceProfile) Run(ctx context.Context, state multistep.StateBag) multistep.StepAction {
|
||||
iamsvc := state.Get("iam").(*iam.IAM)
|
||||
ui := state.Get("ui").(packer.Ui)
|
||||
|
||||
state.Put("iamInstanceProfile", "")
|
||||
|
||||
if len(s.IamInstanceProfile) > 0 {
|
||||
_, err := iamsvc.GetInstanceProfile(
|
||||
&iam.GetInstanceProfileInput{
|
||||
InstanceProfileName: aws.String(s.IamInstanceProfile),
|
||||
},
|
||||
)
|
||||
if err != nil {
|
||||
err := fmt.Errorf("Couldn't find specified instance profile: %s", err)
|
||||
log.Printf("[DEBUG] %s", err.Error())
|
||||
state.Put("error", err)
|
||||
return multistep.ActionHalt
|
||||
}
|
||||
log.Printf("Using specified instance profile: %v", s.IamInstanceProfile)
|
||||
state.Put("iamInstanceProfile", s.IamInstanceProfile)
|
||||
return multistep.ActionContinue
|
||||
}
|
||||
|
||||
if s.TemporaryIamInstanceProfilePolicyDocument != nil {
|
||||
// Create the profile
|
||||
profileName := fmt.Sprintf("packer-%s", uuid.TimeOrderedUUID())
|
||||
|
||||
policy, err := json.Marshal(s.TemporaryIamInstanceProfilePolicyDocument)
|
||||
if err != nil {
|
||||
ui.Error(err.Error())
|
||||
state.Put("error", err)
|
||||
return multistep.ActionHalt
|
||||
}
|
||||
|
||||
ui.Say(fmt.Sprintf("Creating temporary instance profile for this instance: %s", profileName))
|
||||
|
||||
profileResp, err := iamsvc.CreateInstanceProfile(&iam.CreateInstanceProfileInput{
|
||||
InstanceProfileName: aws.String(profileName),
|
||||
})
|
||||
if err != nil {
|
||||
ui.Error(err.Error())
|
||||
state.Put("error", err)
|
||||
return multistep.ActionHalt
|
||||
}
|
||||
s.createdInstanceProfileName = aws.StringValue(profileResp.InstanceProfile.InstanceProfileName)
|
||||
|
||||
log.Printf("[DEBUG] Waiting for temporary instance profile: %s", s.createdInstanceProfileName)
|
||||
err = iamsvc.WaitUntilInstanceProfileExists(&iam.GetInstanceProfileInput{
|
||||
InstanceProfileName: aws.String(s.createdInstanceProfileName),
|
||||
})
|
||||
|
||||
if err == nil {
|
||||
log.Printf("[DEBUG] Found instance profile %s", s.createdInstanceProfileName)
|
||||
} else {
|
||||
err := fmt.Errorf("Timed out waiting for instance profile %s: %s", s.createdInstanceProfileName, err)
|
||||
log.Printf("[DEBUG] %s", err.Error())
|
||||
state.Put("error", err)
|
||||
return multistep.ActionHalt
|
||||
}
|
||||
|
||||
ui.Say(fmt.Sprintf("Creating temporary role for this instance: %s", profileName))
|
||||
|
||||
roleResp, err := iamsvc.CreateRole(&iam.CreateRoleInput{
|
||||
RoleName: aws.String(profileName),
|
||||
Description: aws.String("Temporary role for Packer"),
|
||||
AssumeRolePolicyDocument: aws.String("{\"Version\": \"2012-10-17\",\"Statement\": [{\"Effect\": \"Allow\",\"Principal\": {\"Service\": \"ec2.amazonaws.com\"},\"Action\": \"sts:AssumeRole\"}]}"),
|
||||
})
|
||||
if err != nil {
|
||||
ui.Error(err.Error())
|
||||
state.Put("error", err)
|
||||
return multistep.ActionHalt
|
||||
}
|
||||
|
||||
s.createdRoleName = aws.StringValue(roleResp.Role.RoleName)
|
||||
|
||||
log.Printf("[DEBUG] Waiting for temporary role: %s", s.createdInstanceProfileName)
|
||||
err = iamsvc.WaitUntilRoleExists(&iam.GetRoleInput{
|
||||
RoleName: aws.String(s.createdRoleName),
|
||||
})
|
||||
if err == nil {
|
||||
log.Printf("[DEBUG] Found temporary role %s", s.createdRoleName)
|
||||
} else {
|
||||
err := fmt.Errorf("Timed out waiting for temporary role %s: %s", s.createdRoleName, err)
|
||||
log.Printf("[DEBUG] %s", err.Error())
|
||||
state.Put("error", err)
|
||||
return multistep.ActionHalt
|
||||
}
|
||||
|
||||
ui.Say(fmt.Sprintf("Attaching policy to the temporary role: %s", profileName))
|
||||
|
||||
_, err = iamsvc.PutRolePolicy(&iam.PutRolePolicyInput{
|
||||
RoleName: roleResp.Role.RoleName,
|
||||
PolicyName: aws.String(profileName),
|
||||
PolicyDocument: aws.String(string(policy)),
|
||||
})
|
||||
if err != nil {
|
||||
ui.Error(err.Error())
|
||||
state.Put("error", err)
|
||||
return multistep.ActionHalt
|
||||
}
|
||||
|
||||
s.createdPolicyName = aws.StringValue(roleResp.Role.RoleName)
|
||||
|
||||
_, err = iamsvc.AddRoleToInstanceProfile(&iam.AddRoleToInstanceProfileInput{
|
||||
RoleName: roleResp.Role.RoleName,
|
||||
InstanceProfileName: profileResp.InstanceProfile.InstanceProfileName,
|
||||
})
|
||||
if err != nil {
|
||||
ui.Error(err.Error())
|
||||
state.Put("error", err)
|
||||
return multistep.ActionHalt
|
||||
}
|
||||
|
||||
s.roleIsAttached = true
|
||||
state.Put("iamInstanceProfile", aws.StringValue(profileResp.InstanceProfile.InstanceProfileName))
|
||||
|
||||
time.Sleep(5 * time.Second)
|
||||
}
|
||||
|
||||
return multistep.ActionContinue
|
||||
}
|
||||
|
||||
func (s *StepIamInstanceProfile) Cleanup(state multistep.StateBag) {
|
||||
iamsvc := state.Get("iam").(*iam.IAM)
|
||||
ui := state.Get("ui").(packer.Ui)
|
||||
var err error
|
||||
|
||||
if s.roleIsAttached == true {
|
||||
ui.Say("Detaching temporary role from instance profile...")
|
||||
|
||||
_, err := iamsvc.RemoveRoleFromInstanceProfile(&iam.RemoveRoleFromInstanceProfileInput{
|
||||
InstanceProfileName: aws.String(s.createdInstanceProfileName),
|
||||
RoleName: aws.String(s.createdRoleName),
|
||||
})
|
||||
if err != nil {
|
||||
ui.Error(fmt.Sprintf(
|
||||
"Error %s. Please delete the role manually: %s", err.Error(), s.createdRoleName))
|
||||
}
|
||||
}
|
||||
|
||||
if s.createdPolicyName != "" {
|
||||
ui.Say("Removing policy from temporary role...")
|
||||
iamsvc.DeleteRolePolicy(&iam.DeleteRolePolicyInput{
|
||||
PolicyName: aws.String(s.createdPolicyName),
|
||||
RoleName: aws.String(s.createdRoleName),
|
||||
})
|
||||
}
|
||||
if s.createdRoleName != "" {
|
||||
ui.Say("Deleting temporary role...")
|
||||
|
||||
_, err = iamsvc.DeleteRole(&iam.DeleteRoleInput{RoleName: &s.createdRoleName})
|
||||
if err != nil {
|
||||
ui.Error(fmt.Sprintf(
|
||||
"Error %s. Please delete the role manually: %s", err.Error(), s.createdRoleName))
|
||||
}
|
||||
}
|
||||
|
||||
if s.createdInstanceProfileName != "" {
|
||||
ui.Say("Deleting temporary instance profile...")
|
||||
|
||||
_, err = iamsvc.DeleteInstanceProfile(&iam.DeleteInstanceProfileInput{
|
||||
InstanceProfileName: &s.createdInstanceProfileName})
|
||||
|
||||
if err != nil {
|
||||
ui.Error(fmt.Sprintf(
|
||||
"Error %s. Please delete the instance profile manually: %s", err.Error(), s.createdInstanceProfileName))
|
||||
}
|
||||
}
|
||||
}
|
|
@ -28,7 +28,6 @@ type StepRunSourceInstance struct {
|
|||
EbsOptimized bool
|
||||
EnableT2Unlimited bool
|
||||
ExpectedRootDevice string
|
||||
IamInstanceProfile string
|
||||
InstanceInitiatedShutdownBehavior string
|
||||
InstanceType string
|
||||
IsRestricted bool
|
||||
|
@ -45,6 +44,8 @@ func (s *StepRunSourceInstance) Run(ctx context.Context, state multistep.StateBa
|
|||
ec2conn := state.Get("ec2").(*ec2.EC2)
|
||||
|
||||
securityGroupIds := aws.StringSlice(state.Get("securityGroupIds").([]string))
|
||||
iamInstanceProfile := aws.String(state.Get("iamInstanceProfile").(string))
|
||||
|
||||
ui := state.Get("ui").(packer.Ui)
|
||||
|
||||
userData := s.UserData
|
||||
|
@ -110,7 +111,7 @@ func (s *StepRunSourceInstance) Run(ctx context.Context, state multistep.StateBa
|
|||
UserData: &userData,
|
||||
MaxCount: aws.Int64(1),
|
||||
MinCount: aws.Int64(1),
|
||||
IamInstanceProfile: &ec2.IamInstanceProfileSpecification{Name: &s.IamInstanceProfile},
|
||||
IamInstanceProfile: &ec2.IamInstanceProfileSpecification{Name: iamInstanceProfile},
|
||||
BlockDeviceMappings: s.LaunchMappings.BuildEC2BlockDeviceMappings(),
|
||||
Placement: &ec2.Placement{AvailabilityZone: &az},
|
||||
EbsOptimized: &s.EbsOptimized,
|
||||
|
|
|
@ -31,7 +31,6 @@ type StepRunSpotInstance struct {
|
|||
Comm *communicator.Config
|
||||
EbsOptimized bool
|
||||
ExpectedRootDevice string
|
||||
IamInstanceProfile string
|
||||
InstanceInitiatedShutdownBehavior string
|
||||
InstanceType string
|
||||
SourceAMI string
|
||||
|
@ -69,12 +68,14 @@ func (s *StepRunSpotInstance) CreateTemplateData(userData *string, az string,
|
|||
launchMappingRequests = append(launchMappingRequests, launchRequest)
|
||||
}
|
||||
|
||||
iamInstanceProfile := aws.String(state.Get("iamInstanceProfile").(string))
|
||||
|
||||
// Create a launch template.
|
||||
templateData := ec2.RequestLaunchTemplateData{
|
||||
BlockDeviceMappings: launchMappingRequests,
|
||||
DisableApiTermination: aws.Bool(false),
|
||||
EbsOptimized: &s.EbsOptimized,
|
||||
IamInstanceProfile: &ec2.LaunchTemplateIamInstanceProfileSpecificationRequest{Name: &s.IamInstanceProfile},
|
||||
IamInstanceProfile: &ec2.LaunchTemplateIamInstanceProfileSpecificationRequest{Name: iamInstanceProfile},
|
||||
ImageId: &s.SourceAMI,
|
||||
InstanceMarketOptions: marketOptions,
|
||||
Placement: &ec2.LaunchTemplatePlacementRequest{
|
||||
|
|
|
@ -2,6 +2,7 @@ package common
|
|||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
|
@ -73,6 +74,7 @@ func tStateSpot() multistep.StateBag {
|
|||
})
|
||||
state.Put("availability_zone", "us-east-1c")
|
||||
state.Put("securityGroupIds", []string{"sg-0b8984db72f213dc3"})
|
||||
state.Put("iamInstanceProfile", "packer-123")
|
||||
state.Put("subnet_id", "subnet-077fde4e")
|
||||
state.Put("source_image", "")
|
||||
return state
|
||||
|
@ -91,7 +93,6 @@ func getBasicStep() *StepRunSpotInstance {
|
|||
},
|
||||
EbsOptimized: false,
|
||||
ExpectedRootDevice: "ebs",
|
||||
IamInstanceProfile: "",
|
||||
InstanceInitiatedShutdownBehavior: "stop",
|
||||
InstanceType: "t2.micro",
|
||||
SourceAMI: "",
|
||||
|
@ -125,6 +126,10 @@ func TestCreateTemplateData(t *testing.T) {
|
|||
t.Fatalf("Template should have contained a networkInterface object: recieved %#v", template.NetworkInterfaces)
|
||||
}
|
||||
|
||||
if *template.IamInstanceProfile.Name != state.Get("iamInstanceProfile") {
|
||||
t.Fatalf("Template should have contained a InstanceProfile name: recieved %#v", template.IamInstanceProfile.Name)
|
||||
}
|
||||
|
||||
// Rerun, this time testing that we set security group IDs
|
||||
state.Put("subnet_id", "")
|
||||
template = stepRunSpotInstance.CreateTemplateData(aws.String("userdata"), "az", state,
|
||||
|
@ -132,4 +137,13 @@ func TestCreateTemplateData(t *testing.T) {
|
|||
if template.NetworkInterfaces != nil {
|
||||
t.Fatalf("Template shouldn't contain network interfaces object if subnet_id is unset.")
|
||||
}
|
||||
|
||||
// Rerun, this time testing that instance doesn't have instance profile is iamInstanceProfile is unset
|
||||
state.Put("iamInstanceProfile", "")
|
||||
template = stepRunSpotInstance.CreateTemplateData(aws.String("userdata"), "az", state,
|
||||
&ec2.LaunchTemplateInstanceMarketOptionsRequest{})
|
||||
fmt.Println(template.IamInstanceProfile)
|
||||
if *template.IamInstanceProfile.Name != "" {
|
||||
t.Fatalf("Template shouldn't contain instance profile if iamInstanceProfile is unset.")
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,6 +12,7 @@ import (
|
|||
"fmt"
|
||||
|
||||
"github.com/aws/aws-sdk-go/service/ec2"
|
||||
"github.com/aws/aws-sdk-go/service/iam"
|
||||
awscommon "github.com/hashicorp/packer/builder/amazon/common"
|
||||
"github.com/hashicorp/packer/common"
|
||||
"github.com/hashicorp/packer/helper/communicator"
|
||||
|
@ -126,13 +127,14 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack
|
|||
}
|
||||
|
||||
ec2conn := ec2.New(session)
|
||||
|
||||
iam := iam.New(session)
|
||||
// Setup the state bag and initial state for the steps
|
||||
state := new(multistep.BasicStateBag)
|
||||
state.Put("config", &b.config)
|
||||
state.Put("access_config", &b.config.AccessConfig)
|
||||
state.Put("ami_config", &b.config.AMIConfig)
|
||||
state.Put("ec2", ec2conn)
|
||||
state.Put("iam", iam)
|
||||
state.Put("awsSession", session)
|
||||
state.Put("hook", hook)
|
||||
state.Put("ui", ui)
|
||||
|
@ -149,7 +151,6 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack
|
|||
Debug: b.config.PackerDebug,
|
||||
EbsOptimized: b.config.EbsOptimized,
|
||||
ExpectedRootDevice: "ebs",
|
||||
IamInstanceProfile: b.config.IamInstanceProfile,
|
||||
InstanceInitiatedShutdownBehavior: b.config.InstanceInitiatedShutdownBehavior,
|
||||
InstanceType: b.config.InstanceType,
|
||||
SourceAMI: b.config.SourceAmi,
|
||||
|
@ -171,7 +172,6 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack
|
|||
EbsOptimized: b.config.EbsOptimized,
|
||||
EnableT2Unlimited: b.config.EnableT2Unlimited,
|
||||
ExpectedRootDevice: "ebs",
|
||||
IamInstanceProfile: b.config.IamInstanceProfile,
|
||||
InstanceInitiatedShutdownBehavior: b.config.InstanceInitiatedShutdownBehavior,
|
||||
InstanceType: b.config.InstanceType,
|
||||
IsRestricted: b.config.IsChinaCloud() || b.config.IsGovCloud(),
|
||||
|
@ -217,6 +217,10 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack
|
|||
CommConfig: &b.config.RunConfig.Comm,
|
||||
TemporarySGSourceCidrs: b.config.TemporarySGSourceCidrs,
|
||||
},
|
||||
&awscommon.StepIamInstanceProfile{
|
||||
IamInstanceProfile: b.config.IamInstanceProfile,
|
||||
TemporaryIamInstanceProfilePolicyDocument: b.config.TemporaryIamInstanceProfilePolicyDocument,
|
||||
},
|
||||
&awscommon.StepCleanupVolumes{
|
||||
LaunchMappings: b.config.LaunchMappings,
|
||||
},
|
||||
|
|
|
@ -8,6 +8,7 @@ import (
|
|||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"github.com/aws/aws-sdk-go/service/iam"
|
||||
|
||||
"github.com/aws/aws-sdk-go/service/ec2"
|
||||
awscommon "github.com/hashicorp/packer/builder/amazon/common"
|
||||
|
@ -164,7 +165,9 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack
|
|||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
ec2conn := ec2.New(session)
|
||||
iam := iam.New(session)
|
||||
|
||||
// Setup the state bag and initial state for the steps
|
||||
state := new(multistep.BasicStateBag)
|
||||
|
@ -172,6 +175,7 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack
|
|||
state.Put("access_config", &b.config.AccessConfig)
|
||||
state.Put("ami_config", &b.config.AMIConfig)
|
||||
state.Put("ec2", ec2conn)
|
||||
state.Put("iam", iam)
|
||||
state.Put("awsSession", session)
|
||||
state.Put("hook", hook)
|
||||
state.Put("ui", ui)
|
||||
|
@ -188,7 +192,6 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack
|
|||
Debug: b.config.PackerDebug,
|
||||
EbsOptimized: b.config.EbsOptimized,
|
||||
ExpectedRootDevice: "ebs",
|
||||
IamInstanceProfile: b.config.IamInstanceProfile,
|
||||
InstanceInitiatedShutdownBehavior: b.config.InstanceInitiatedShutdownBehavior,
|
||||
InstanceType: b.config.InstanceType,
|
||||
SourceAMI: b.config.SourceAmi,
|
||||
|
@ -210,7 +213,6 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack
|
|||
EbsOptimized: b.config.EbsOptimized,
|
||||
EnableT2Unlimited: b.config.EnableT2Unlimited,
|
||||
ExpectedRootDevice: "ebs",
|
||||
IamInstanceProfile: b.config.IamInstanceProfile,
|
||||
InstanceInitiatedShutdownBehavior: b.config.InstanceInitiatedShutdownBehavior,
|
||||
InstanceType: b.config.InstanceType,
|
||||
IsRestricted: b.config.IsChinaCloud() || b.config.IsGovCloud(),
|
||||
|
@ -258,6 +260,10 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack
|
|||
CommConfig: &b.config.RunConfig.Comm,
|
||||
TemporarySGSourceCidrs: b.config.TemporarySGSourceCidrs,
|
||||
},
|
||||
&awscommon.StepIamInstanceProfile{
|
||||
IamInstanceProfile: b.config.IamInstanceProfile,
|
||||
TemporaryIamInstanceProfilePolicyDocument: b.config.TemporaryIamInstanceProfilePolicyDocument,
|
||||
},
|
||||
&awscommon.StepCleanupVolumes{
|
||||
LaunchMappings: b.config.LaunchMappings.Common(),
|
||||
},
|
||||
|
|
|
@ -9,6 +9,7 @@ import (
|
|||
"fmt"
|
||||
|
||||
"github.com/aws/aws-sdk-go/service/ec2"
|
||||
"github.com/aws/aws-sdk-go/service/iam"
|
||||
awscommon "github.com/hashicorp/packer/builder/amazon/common"
|
||||
"github.com/hashicorp/packer/common"
|
||||
"github.com/hashicorp/packer/helper/communicator"
|
||||
|
@ -141,12 +142,14 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack
|
|||
return nil, err
|
||||
}
|
||||
ec2conn := ec2.New(session)
|
||||
iam := iam.New(session)
|
||||
|
||||
// Setup the state bag and initial state for the steps
|
||||
state := new(multistep.BasicStateBag)
|
||||
state.Put("config", &b.config)
|
||||
state.Put("access_config", &b.config.AccessConfig)
|
||||
state.Put("ec2", ec2conn)
|
||||
state.Put("iam", iam)
|
||||
state.Put("hook", hook)
|
||||
state.Put("ui", ui)
|
||||
|
||||
|
@ -162,7 +165,6 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack
|
|||
Debug: b.config.PackerDebug,
|
||||
EbsOptimized: b.config.EbsOptimized,
|
||||
ExpectedRootDevice: "ebs",
|
||||
IamInstanceProfile: b.config.IamInstanceProfile,
|
||||
InstanceInitiatedShutdownBehavior: b.config.InstanceInitiatedShutdownBehavior,
|
||||
InstanceType: b.config.InstanceType,
|
||||
SourceAMI: b.config.SourceAmi,
|
||||
|
@ -184,7 +186,6 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack
|
|||
EbsOptimized: b.config.EbsOptimized,
|
||||
EnableT2Unlimited: b.config.EnableT2Unlimited,
|
||||
ExpectedRootDevice: "ebs",
|
||||
IamInstanceProfile: b.config.IamInstanceProfile,
|
||||
InstanceInitiatedShutdownBehavior: b.config.InstanceInitiatedShutdownBehavior,
|
||||
InstanceType: b.config.InstanceType,
|
||||
IsRestricted: b.config.IsChinaCloud() || b.config.IsGovCloud(),
|
||||
|
@ -224,6 +225,10 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack
|
|||
CommConfig: &b.config.RunConfig.Comm,
|
||||
TemporarySGSourceCidrs: b.config.TemporarySGSourceCidrs,
|
||||
},
|
||||
&awscommon.StepIamInstanceProfile{
|
||||
IamInstanceProfile: b.config.IamInstanceProfile,
|
||||
TemporaryIamInstanceProfilePolicyDocument: b.config.TemporaryIamInstanceProfilePolicyDocument,
|
||||
},
|
||||
instanceStep,
|
||||
&stepTagEBSVolumes{
|
||||
VolumeMapping: b.config.VolumeMappings,
|
||||
|
|
|
@ -8,6 +8,7 @@ import (
|
|||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"github.com/aws/aws-sdk-go/service/iam"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
|
@ -229,6 +230,7 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack
|
|||
return nil, err
|
||||
}
|
||||
ec2conn := ec2.New(session)
|
||||
iam := iam.New(session)
|
||||
|
||||
// Setup the state bag and initial state for the steps
|
||||
state := new(multistep.BasicStateBag)
|
||||
|
@ -236,6 +238,7 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack
|
|||
state.Put("access_config", &b.config.AccessConfig)
|
||||
state.Put("ami_config", &b.config.AMIConfig)
|
||||
state.Put("ec2", ec2conn)
|
||||
state.Put("iam", iam)
|
||||
state.Put("awsSession", session)
|
||||
state.Put("hook", hook)
|
||||
state.Put("ui", ui)
|
||||
|
@ -251,7 +254,6 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack
|
|||
Comm: &b.config.RunConfig.Comm,
|
||||
Debug: b.config.PackerDebug,
|
||||
EbsOptimized: b.config.EbsOptimized,
|
||||
IamInstanceProfile: b.config.IamInstanceProfile,
|
||||
InstanceType: b.config.InstanceType,
|
||||
SourceAMI: b.config.SourceAmi,
|
||||
SpotPrice: b.config.SpotPrice,
|
||||
|
@ -270,7 +272,6 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack
|
|||
Debug: b.config.PackerDebug,
|
||||
EbsOptimized: b.config.EbsOptimized,
|
||||
EnableT2Unlimited: b.config.EnableT2Unlimited,
|
||||
IamInstanceProfile: b.config.IamInstanceProfile,
|
||||
InstanceType: b.config.InstanceType,
|
||||
IsRestricted: b.config.IsChinaCloud() || b.config.IsGovCloud(),
|
||||
SourceAMI: b.config.SourceAmi,
|
||||
|
@ -313,6 +314,10 @@ func (b *Builder) Run(ctx context.Context, ui packer.Ui, hook packer.Hook) (pack
|
|||
SecurityGroupIds: b.config.SecurityGroupIds,
|
||||
TemporarySGSourceCidrs: b.config.TemporarySGSourceCidrs,
|
||||
},
|
||||
&awscommon.StepIamInstanceProfile{
|
||||
IamInstanceProfile: b.config.IamInstanceProfile,
|
||||
TemporaryIamInstanceProfilePolicyDocument: b.config.TemporaryIamInstanceProfilePolicyDocument,
|
||||
},
|
||||
instanceStep,
|
||||
&awscommon.StepGetPassword{
|
||||
Debug: b.config.PackerDebug,
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,80 @@
|
|||
// Code generated by private/model/cli/gen-api/main.go. DO NOT EDIT.
|
||||
|
||||
// Package iam provides the client and types for making API
|
||||
// requests to AWS Identity and Access Management.
|
||||
//
|
||||
// AWS Identity and Access Management (IAM) is a web service that you can use
|
||||
// to manage users and user permissions under your AWS account. This guide provides
|
||||
// descriptions of IAM actions that you can call programmatically. For general
|
||||
// information about IAM, see AWS Identity and Access Management (IAM) (http://aws.amazon.com/iam/).
|
||||
// For the user guide for IAM, see Using IAM (https://docs.aws.amazon.com/IAM/latest/UserGuide/).
|
||||
//
|
||||
// AWS provides SDKs that consist of libraries and sample code for various programming
|
||||
// languages and platforms (Java, Ruby, .NET, iOS, Android, etc.). The SDKs
|
||||
// provide a convenient way to create programmatic access to IAM and AWS. For
|
||||
// example, the SDKs take care of tasks such as cryptographically signing requests
|
||||
// (see below), managing errors, and retrying requests automatically. For information
|
||||
// about the AWS SDKs, including how to download and install them, see the Tools
|
||||
// for Amazon Web Services (http://aws.amazon.com/tools/) page.
|
||||
//
|
||||
// We recommend that you use the AWS SDKs to make programmatic API calls to
|
||||
// IAM. However, you can also use the IAM Query API to make direct calls to
|
||||
// the IAM web service. To learn more about the IAM Query API, see Making Query
|
||||
// Requests (https://docs.aws.amazon.com/IAM/latest/UserGuide/IAM_UsingQueryAPI.html)
|
||||
// in the Using IAM guide. IAM supports GET and POST requests for all actions.
|
||||
// That is, the API does not require you to use GET for some actions and POST
|
||||
// for others. However, GET requests are subject to the limitation size of a
|
||||
// URL. Therefore, for operations that require larger sizes, use a POST request.
|
||||
//
|
||||
// Signing Requests
|
||||
//
|
||||
// Requests must be signed using an access key ID and a secret access key. We
|
||||
// strongly recommend that you do not use your AWS account access key ID and
|
||||
// secret access key for everyday work with IAM. You can use the access key
|
||||
// ID and secret access key for an IAM user or you can use the AWS Security
|
||||
// Token Service to generate temporary security credentials and use those to
|
||||
// sign requests.
|
||||
//
|
||||
// To sign requests, we recommend that you use Signature Version 4 (https://docs.aws.amazon.com/general/latest/gr/signature-version-4.html).
|
||||
// If you have an existing application that uses Signature Version 2, you do
|
||||
// not have to update it to use Signature Version 4. However, some operations
|
||||
// now require Signature Version 4. The documentation for operations that require
|
||||
// version 4 indicate this requirement.
|
||||
//
|
||||
// Additional Resources
|
||||
//
|
||||
// For more information, see the following:
|
||||
//
|
||||
// * AWS Security Credentials (https://docs.aws.amazon.com/general/latest/gr/aws-security-credentials.html).
|
||||
// This topic provides general information about the types of credentials
|
||||
// used for accessing AWS.
|
||||
//
|
||||
// * IAM Best Practices (https://docs.aws.amazon.com/IAM/latest/UserGuide/IAMBestPractices.html).
|
||||
// This topic presents a list of suggestions for using the IAM service to
|
||||
// help secure your AWS resources.
|
||||
//
|
||||
// * Signing AWS API Requests (https://docs.aws.amazon.com/general/latest/gr/signing_aws_api_requests.html).
|
||||
// This set of topics walk you through the process of signing a request using
|
||||
// an access key ID and secret access key.
|
||||
//
|
||||
// See https://docs.aws.amazon.com/goto/WebAPI/iam-2010-05-08 for more information on this service.
|
||||
//
|
||||
// See iam package documentation for more information.
|
||||
// https://docs.aws.amazon.com/sdk-for-go/api/service/iam/
|
||||
//
|
||||
// Using the Client
|
||||
//
|
||||
// To contact AWS Identity and Access Management with the SDK use the New function to create
|
||||
// a new service client. With that client you can make API requests to the service.
|
||||
// These clients are safe to use concurrently.
|
||||
//
|
||||
// See the SDK's documentation for more information on how to use the SDK.
|
||||
// https://docs.aws.amazon.com/sdk-for-go/api/
|
||||
//
|
||||
// See aws.Config documentation for more information on configuring SDK clients.
|
||||
// https://docs.aws.amazon.com/sdk-for-go/api/aws/#Config
|
||||
//
|
||||
// See the AWS Identity and Access Management client IAM for more
|
||||
// information on creating client for this service.
|
||||
// https://docs.aws.amazon.com/sdk-for-go/api/service/iam/#New
|
||||
package iam
|
|
@ -0,0 +1,200 @@
|
|||
// Code generated by private/model/cli/gen-api/main.go. DO NOT EDIT.
|
||||
|
||||
package iam
|
||||
|
||||
const (
|
||||
|
||||
// ErrCodeConcurrentModificationException for service response error code
|
||||
// "ConcurrentModification".
|
||||
//
|
||||
// The request was rejected because multiple requests to change this object
|
||||
// were submitted simultaneously. Wait a few minutes and submit your request
|
||||
// again.
|
||||
ErrCodeConcurrentModificationException = "ConcurrentModification"
|
||||
|
||||
// ErrCodeCredentialReportExpiredException for service response error code
|
||||
// "ReportExpired".
|
||||
//
|
||||
// The request was rejected because the most recent credential report has expired.
|
||||
// To generate a new credential report, use GenerateCredentialReport. For more
|
||||
// information about credential report expiration, see Getting Credential Reports
|
||||
// (https://docs.aws.amazon.com/IAM/latest/UserGuide/credential-reports.html)
|
||||
// in the IAM User Guide.
|
||||
ErrCodeCredentialReportExpiredException = "ReportExpired"
|
||||
|
||||
// ErrCodeCredentialReportNotPresentException for service response error code
|
||||
// "ReportNotPresent".
|
||||
//
|
||||
// The request was rejected because the credential report does not exist. To
|
||||
// generate a credential report, use GenerateCredentialReport.
|
||||
ErrCodeCredentialReportNotPresentException = "ReportNotPresent"
|
||||
|
||||
// ErrCodeCredentialReportNotReadyException for service response error code
|
||||
// "ReportInProgress".
|
||||
//
|
||||
// The request was rejected because the credential report is still being generated.
|
||||
ErrCodeCredentialReportNotReadyException = "ReportInProgress"
|
||||
|
||||
// ErrCodeDeleteConflictException for service response error code
|
||||
// "DeleteConflict".
|
||||
//
|
||||
// The request was rejected because it attempted to delete a resource that has
|
||||
// attached subordinate entities. The error message describes these entities.
|
||||
ErrCodeDeleteConflictException = "DeleteConflict"
|
||||
|
||||
// ErrCodeDuplicateCertificateException for service response error code
|
||||
// "DuplicateCertificate".
|
||||
//
|
||||
// The request was rejected because the same certificate is associated with
|
||||
// an IAM user in the account.
|
||||
ErrCodeDuplicateCertificateException = "DuplicateCertificate"
|
||||
|
||||
// ErrCodeDuplicateSSHPublicKeyException for service response error code
|
||||
// "DuplicateSSHPublicKey".
|
||||
//
|
||||
// The request was rejected because the SSH public key is already associated
|
||||
// with the specified IAM user.
|
||||
ErrCodeDuplicateSSHPublicKeyException = "DuplicateSSHPublicKey"
|
||||
|
||||
// ErrCodeEntityAlreadyExistsException for service response error code
|
||||
// "EntityAlreadyExists".
|
||||
//
|
||||
// The request was rejected because it attempted to create a resource that already
|
||||
// exists.
|
||||
ErrCodeEntityAlreadyExistsException = "EntityAlreadyExists"
|
||||
|
||||
// ErrCodeEntityTemporarilyUnmodifiableException for service response error code
|
||||
// "EntityTemporarilyUnmodifiable".
|
||||
//
|
||||
// The request was rejected because it referenced an entity that is temporarily
|
||||
// unmodifiable, such as a user name that was deleted and then recreated. The
|
||||
// error indicates that the request is likely to succeed if you try again after
|
||||
// waiting several minutes. The error message describes the entity.
|
||||
ErrCodeEntityTemporarilyUnmodifiableException = "EntityTemporarilyUnmodifiable"
|
||||
|
||||
// ErrCodeInvalidAuthenticationCodeException for service response error code
|
||||
// "InvalidAuthenticationCode".
|
||||
//
|
||||
// The request was rejected because the authentication code was not recognized.
|
||||
// The error message describes the specific error.
|
||||
ErrCodeInvalidAuthenticationCodeException = "InvalidAuthenticationCode"
|
||||
|
||||
// ErrCodeInvalidCertificateException for service response error code
|
||||
// "InvalidCertificate".
|
||||
//
|
||||
// The request was rejected because the certificate is invalid.
|
||||
ErrCodeInvalidCertificateException = "InvalidCertificate"
|
||||
|
||||
// ErrCodeInvalidInputException for service response error code
|
||||
// "InvalidInput".
|
||||
//
|
||||
// The request was rejected because an invalid or out-of-range value was supplied
|
||||
// for an input parameter.
|
||||
ErrCodeInvalidInputException = "InvalidInput"
|
||||
|
||||
// ErrCodeInvalidPublicKeyException for service response error code
|
||||
// "InvalidPublicKey".
|
||||
//
|
||||
// The request was rejected because the public key is malformed or otherwise
|
||||
// invalid.
|
||||
ErrCodeInvalidPublicKeyException = "InvalidPublicKey"
|
||||
|
||||
// ErrCodeInvalidUserTypeException for service response error code
|
||||
// "InvalidUserType".
|
||||
//
|
||||
// The request was rejected because the type of user for the transaction was
|
||||
// incorrect.
|
||||
ErrCodeInvalidUserTypeException = "InvalidUserType"
|
||||
|
||||
// ErrCodeKeyPairMismatchException for service response error code
|
||||
// "KeyPairMismatch".
|
||||
//
|
||||
// The request was rejected because the public key certificate and the private
|
||||
// key do not match.
|
||||
ErrCodeKeyPairMismatchException = "KeyPairMismatch"
|
||||
|
||||
// ErrCodeLimitExceededException for service response error code
|
||||
// "LimitExceeded".
|
||||
//
|
||||
// The request was rejected because it attempted to create resources beyond
|
||||
// the current AWS account limits. The error message describes the limit exceeded.
|
||||
ErrCodeLimitExceededException = "LimitExceeded"
|
||||
|
||||
// ErrCodeMalformedCertificateException for service response error code
|
||||
// "MalformedCertificate".
|
||||
//
|
||||
// The request was rejected because the certificate was malformed or expired.
|
||||
// The error message describes the specific error.
|
||||
ErrCodeMalformedCertificateException = "MalformedCertificate"
|
||||
|
||||
// ErrCodeMalformedPolicyDocumentException for service response error code
|
||||
// "MalformedPolicyDocument".
|
||||
//
|
||||
// The request was rejected because the policy document was malformed. The error
|
||||
// message describes the specific error.
|
||||
ErrCodeMalformedPolicyDocumentException = "MalformedPolicyDocument"
|
||||
|
||||
// ErrCodeNoSuchEntityException for service response error code
|
||||
// "NoSuchEntity".
|
||||
//
|
||||
// The request was rejected because it referenced a resource entity that does
|
||||
// not exist. The error message describes the resource.
|
||||
ErrCodeNoSuchEntityException = "NoSuchEntity"
|
||||
|
||||
// ErrCodePasswordPolicyViolationException for service response error code
|
||||
// "PasswordPolicyViolation".
|
||||
//
|
||||
// The request was rejected because the provided password did not meet the requirements
|
||||
// imposed by the account password policy.
|
||||
ErrCodePasswordPolicyViolationException = "PasswordPolicyViolation"
|
||||
|
||||
// ErrCodePolicyEvaluationException for service response error code
|
||||
// "PolicyEvaluation".
|
||||
//
|
||||
// The request failed because a provided policy could not be successfully evaluated.
|
||||
// An additional detailed message indicates the source of the failure.
|
||||
ErrCodePolicyEvaluationException = "PolicyEvaluation"
|
||||
|
||||
// ErrCodePolicyNotAttachableException for service response error code
|
||||
// "PolicyNotAttachable".
|
||||
//
|
||||
// The request failed because AWS service role policies can only be attached
|
||||
// to the service-linked role for that service.
|
||||
ErrCodePolicyNotAttachableException = "PolicyNotAttachable"
|
||||
|
||||
// ErrCodeReportGenerationLimitExceededException for service response error code
|
||||
// "ReportGenerationLimitExceeded".
|
||||
//
|
||||
// The request failed because the maximum number of concurrent requests for
|
||||
// this account are already running.
|
||||
ErrCodeReportGenerationLimitExceededException = "ReportGenerationLimitExceeded"
|
||||
|
||||
// ErrCodeServiceFailureException for service response error code
|
||||
// "ServiceFailure".
|
||||
//
|
||||
// The request processing has failed because of an unknown error, exception
|
||||
// or failure.
|
||||
ErrCodeServiceFailureException = "ServiceFailure"
|
||||
|
||||
// ErrCodeServiceNotSupportedException for service response error code
|
||||
// "NotSupportedService".
|
||||
//
|
||||
// The specified service does not support service-specific credentials.
|
||||
ErrCodeServiceNotSupportedException = "NotSupportedService"
|
||||
|
||||
// ErrCodeUnmodifiableEntityException for service response error code
|
||||
// "UnmodifiableEntity".
|
||||
//
|
||||
// The request was rejected because only the service that depends on the service-linked
|
||||
// role can modify or delete the role on your behalf. The error message includes
|
||||
// the name of the service that depends on this service-linked role. You must
|
||||
// request the change through that service.
|
||||
ErrCodeUnmodifiableEntityException = "UnmodifiableEntity"
|
||||
|
||||
// ErrCodeUnrecognizedPublicKeyEncodingException for service response error code
|
||||
// "UnrecognizedPublicKeyEncoding".
|
||||
//
|
||||
// The request was rejected because the public key encoding format is unsupported
|
||||
// or unrecognized.
|
||||
ErrCodeUnrecognizedPublicKeyEncodingException = "UnrecognizedPublicKeyEncoding"
|
||||
)
|
|
@ -0,0 +1,95 @@
|
|||
// Code generated by private/model/cli/gen-api/main.go. DO NOT EDIT.
|
||||
|
||||
package iam
|
||||
|
||||
import (
|
||||
"github.com/aws/aws-sdk-go/aws"
|
||||
"github.com/aws/aws-sdk-go/aws/client"
|
||||
"github.com/aws/aws-sdk-go/aws/client/metadata"
|
||||
"github.com/aws/aws-sdk-go/aws/request"
|
||||
"github.com/aws/aws-sdk-go/aws/signer/v4"
|
||||
"github.com/aws/aws-sdk-go/private/protocol/query"
|
||||
)
|
||||
|
||||
// IAM provides the API operation methods for making requests to
|
||||
// AWS Identity and Access Management. See this package's package overview docs
|
||||
// for details on the service.
|
||||
//
|
||||
// IAM methods are safe to use concurrently. It is not safe to
|
||||
// modify mutate any of the struct's properties though.
|
||||
type IAM struct {
|
||||
*client.Client
|
||||
}
|
||||
|
||||
// Used for custom client initialization logic
|
||||
var initClient func(*client.Client)
|
||||
|
||||
// Used for custom request initialization logic
|
||||
var initRequest func(*request.Request)
|
||||
|
||||
// Service information constants
|
||||
const (
|
||||
ServiceName = "iam" // Name of service.
|
||||
EndpointsID = ServiceName // ID to lookup a service endpoint with.
|
||||
ServiceID = "IAM" // ServiceID is a unique identifer of a specific service.
|
||||
)
|
||||
|
||||
// New creates a new instance of the IAM client with a session.
|
||||
// If additional configuration is needed for the client instance use the optional
|
||||
// aws.Config parameter to add your extra config.
|
||||
//
|
||||
// Example:
|
||||
// // Create a IAM client from just a session.
|
||||
// svc := iam.New(mySession)
|
||||
//
|
||||
// // Create a IAM client with additional configuration
|
||||
// svc := iam.New(mySession, aws.NewConfig().WithRegion("us-west-2"))
|
||||
func New(p client.ConfigProvider, cfgs ...*aws.Config) *IAM {
|
||||
c := p.ClientConfig(EndpointsID, cfgs...)
|
||||
return newClient(*c.Config, c.Handlers, c.Endpoint, c.SigningRegion, c.SigningName)
|
||||
}
|
||||
|
||||
// newClient creates, initializes and returns a new service client instance.
|
||||
func newClient(cfg aws.Config, handlers request.Handlers, endpoint, signingRegion, signingName string) *IAM {
|
||||
svc := &IAM{
|
||||
Client: client.New(
|
||||
cfg,
|
||||
metadata.ClientInfo{
|
||||
ServiceName: ServiceName,
|
||||
ServiceID: ServiceID,
|
||||
SigningName: signingName,
|
||||
SigningRegion: signingRegion,
|
||||
Endpoint: endpoint,
|
||||
APIVersion: "2010-05-08",
|
||||
},
|
||||
handlers,
|
||||
),
|
||||
}
|
||||
|
||||
// Handlers
|
||||
svc.Handlers.Sign.PushBackNamed(v4.SignRequestHandler)
|
||||
svc.Handlers.Build.PushBackNamed(query.BuildHandler)
|
||||
svc.Handlers.Unmarshal.PushBackNamed(query.UnmarshalHandler)
|
||||
svc.Handlers.UnmarshalMeta.PushBackNamed(query.UnmarshalMetaHandler)
|
||||
svc.Handlers.UnmarshalError.PushBackNamed(query.UnmarshalErrorHandler)
|
||||
|
||||
// Run custom client initialization if present
|
||||
if initClient != nil {
|
||||
initClient(svc.Client)
|
||||
}
|
||||
|
||||
return svc
|
||||
}
|
||||
|
||||
// newRequest creates a new request for a IAM operation and runs any
|
||||
// custom request initialization.
|
||||
func (c *IAM) newRequest(op *request.Operation, params, data interface{}) *request.Request {
|
||||
req := c.NewRequest(op, params, data)
|
||||
|
||||
// Run custom request initialization if present
|
||||
if initRequest != nil {
|
||||
initRequest(req)
|
||||
}
|
||||
|
||||
return req
|
||||
}
|
|
@ -0,0 +1,214 @@
|
|||
// Code generated by private/model/cli/gen-api/main.go. DO NOT EDIT.
|
||||
|
||||
package iam
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/aws/aws-sdk-go/aws"
|
||||
"github.com/aws/aws-sdk-go/aws/request"
|
||||
)
|
||||
|
||||
// WaitUntilInstanceProfileExists uses the IAM API operation
|
||||
// GetInstanceProfile to wait for a condition to be met before returning.
|
||||
// If the condition is not met within the max attempt window, an error will
|
||||
// be returned.
|
||||
func (c *IAM) WaitUntilInstanceProfileExists(input *GetInstanceProfileInput) error {
|
||||
return c.WaitUntilInstanceProfileExistsWithContext(aws.BackgroundContext(), input)
|
||||
}
|
||||
|
||||
// WaitUntilInstanceProfileExistsWithContext is an extended version of WaitUntilInstanceProfileExists.
|
||||
// With the support for passing in a context and options to configure the
|
||||
// Waiter and the underlying request options.
|
||||
//
|
||||
// The context must be non-nil and will be used for request cancellation. If
|
||||
// the context is nil a panic will occur. In the future the SDK may create
|
||||
// sub-contexts for http.Requests. See https://golang.org/pkg/context/
|
||||
// for more information on using Contexts.
|
||||
func (c *IAM) WaitUntilInstanceProfileExistsWithContext(ctx aws.Context, input *GetInstanceProfileInput, opts ...request.WaiterOption) error {
|
||||
w := request.Waiter{
|
||||
Name: "WaitUntilInstanceProfileExists",
|
||||
MaxAttempts: 40,
|
||||
Delay: request.ConstantWaiterDelay(1 * time.Second),
|
||||
Acceptors: []request.WaiterAcceptor{
|
||||
{
|
||||
State: request.SuccessWaiterState,
|
||||
Matcher: request.StatusWaiterMatch,
|
||||
Expected: 200,
|
||||
},
|
||||
{
|
||||
State: request.RetryWaiterState,
|
||||
Matcher: request.StatusWaiterMatch,
|
||||
Expected: 404,
|
||||
},
|
||||
},
|
||||
Logger: c.Config.Logger,
|
||||
NewRequest: func(opts []request.Option) (*request.Request, error) {
|
||||
var inCpy *GetInstanceProfileInput
|
||||
if input != nil {
|
||||
tmp := *input
|
||||
inCpy = &tmp
|
||||
}
|
||||
req, _ := c.GetInstanceProfileRequest(inCpy)
|
||||
req.SetContext(ctx)
|
||||
req.ApplyOptions(opts...)
|
||||
return req, nil
|
||||
},
|
||||
}
|
||||
w.ApplyOptions(opts...)
|
||||
|
||||
return w.WaitWithContext(ctx)
|
||||
}
|
||||
|
||||
// WaitUntilPolicyExists uses the IAM API operation
|
||||
// GetPolicy to wait for a condition to be met before returning.
|
||||
// If the condition is not met within the max attempt window, an error will
|
||||
// be returned.
|
||||
func (c *IAM) WaitUntilPolicyExists(input *GetPolicyInput) error {
|
||||
return c.WaitUntilPolicyExistsWithContext(aws.BackgroundContext(), input)
|
||||
}
|
||||
|
||||
// WaitUntilPolicyExistsWithContext is an extended version of WaitUntilPolicyExists.
|
||||
// With the support for passing in a context and options to configure the
|
||||
// Waiter and the underlying request options.
|
||||
//
|
||||
// The context must be non-nil and will be used for request cancellation. If
|
||||
// the context is nil a panic will occur. In the future the SDK may create
|
||||
// sub-contexts for http.Requests. See https://golang.org/pkg/context/
|
||||
// for more information on using Contexts.
|
||||
func (c *IAM) WaitUntilPolicyExistsWithContext(ctx aws.Context, input *GetPolicyInput, opts ...request.WaiterOption) error {
|
||||
w := request.Waiter{
|
||||
Name: "WaitUntilPolicyExists",
|
||||
MaxAttempts: 20,
|
||||
Delay: request.ConstantWaiterDelay(1 * time.Second),
|
||||
Acceptors: []request.WaiterAcceptor{
|
||||
{
|
||||
State: request.SuccessWaiterState,
|
||||
Matcher: request.StatusWaiterMatch,
|
||||
Expected: 200,
|
||||
},
|
||||
{
|
||||
State: request.RetryWaiterState,
|
||||
Matcher: request.ErrorWaiterMatch,
|
||||
Expected: "NoSuchEntity",
|
||||
},
|
||||
},
|
||||
Logger: c.Config.Logger,
|
||||
NewRequest: func(opts []request.Option) (*request.Request, error) {
|
||||
var inCpy *GetPolicyInput
|
||||
if input != nil {
|
||||
tmp := *input
|
||||
inCpy = &tmp
|
||||
}
|
||||
req, _ := c.GetPolicyRequest(inCpy)
|
||||
req.SetContext(ctx)
|
||||
req.ApplyOptions(opts...)
|
||||
return req, nil
|
||||
},
|
||||
}
|
||||
w.ApplyOptions(opts...)
|
||||
|
||||
return w.WaitWithContext(ctx)
|
||||
}
|
||||
|
||||
// WaitUntilRoleExists uses the IAM API operation
|
||||
// GetRole to wait for a condition to be met before returning.
|
||||
// If the condition is not met within the max attempt window, an error will
|
||||
// be returned.
|
||||
func (c *IAM) WaitUntilRoleExists(input *GetRoleInput) error {
|
||||
return c.WaitUntilRoleExistsWithContext(aws.BackgroundContext(), input)
|
||||
}
|
||||
|
||||
// WaitUntilRoleExistsWithContext is an extended version of WaitUntilRoleExists.
|
||||
// With the support for passing in a context and options to configure the
|
||||
// Waiter and the underlying request options.
|
||||
//
|
||||
// The context must be non-nil and will be used for request cancellation. If
|
||||
// the context is nil a panic will occur. In the future the SDK may create
|
||||
// sub-contexts for http.Requests. See https://golang.org/pkg/context/
|
||||
// for more information on using Contexts.
|
||||
func (c *IAM) WaitUntilRoleExistsWithContext(ctx aws.Context, input *GetRoleInput, opts ...request.WaiterOption) error {
|
||||
w := request.Waiter{
|
||||
Name: "WaitUntilRoleExists",
|
||||
MaxAttempts: 20,
|
||||
Delay: request.ConstantWaiterDelay(1 * time.Second),
|
||||
Acceptors: []request.WaiterAcceptor{
|
||||
{
|
||||
State: request.SuccessWaiterState,
|
||||
Matcher: request.StatusWaiterMatch,
|
||||
Expected: 200,
|
||||
},
|
||||
{
|
||||
State: request.RetryWaiterState,
|
||||
Matcher: request.ErrorWaiterMatch,
|
||||
Expected: "NoSuchEntity",
|
||||
},
|
||||
},
|
||||
Logger: c.Config.Logger,
|
||||
NewRequest: func(opts []request.Option) (*request.Request, error) {
|
||||
var inCpy *GetRoleInput
|
||||
if input != nil {
|
||||
tmp := *input
|
||||
inCpy = &tmp
|
||||
}
|
||||
req, _ := c.GetRoleRequest(inCpy)
|
||||
req.SetContext(ctx)
|
||||
req.ApplyOptions(opts...)
|
||||
return req, nil
|
||||
},
|
||||
}
|
||||
w.ApplyOptions(opts...)
|
||||
|
||||
return w.WaitWithContext(ctx)
|
||||
}
|
||||
|
||||
// WaitUntilUserExists uses the IAM API operation
|
||||
// GetUser to wait for a condition to be met before returning.
|
||||
// If the condition is not met within the max attempt window, an error will
|
||||
// be returned.
|
||||
func (c *IAM) WaitUntilUserExists(input *GetUserInput) error {
|
||||
return c.WaitUntilUserExistsWithContext(aws.BackgroundContext(), input)
|
||||
}
|
||||
|
||||
// WaitUntilUserExistsWithContext is an extended version of WaitUntilUserExists.
|
||||
// With the support for passing in a context and options to configure the
|
||||
// Waiter and the underlying request options.
|
||||
//
|
||||
// The context must be non-nil and will be used for request cancellation. If
|
||||
// the context is nil a panic will occur. In the future the SDK may create
|
||||
// sub-contexts for http.Requests. See https://golang.org/pkg/context/
|
||||
// for more information on using Contexts.
|
||||
func (c *IAM) WaitUntilUserExistsWithContext(ctx aws.Context, input *GetUserInput, opts ...request.WaiterOption) error {
|
||||
w := request.Waiter{
|
||||
Name: "WaitUntilUserExists",
|
||||
MaxAttempts: 20,
|
||||
Delay: request.ConstantWaiterDelay(1 * time.Second),
|
||||
Acceptors: []request.WaiterAcceptor{
|
||||
{
|
||||
State: request.SuccessWaiterState,
|
||||
Matcher: request.StatusWaiterMatch,
|
||||
Expected: 200,
|
||||
},
|
||||
{
|
||||
State: request.RetryWaiterState,
|
||||
Matcher: request.ErrorWaiterMatch,
|
||||
Expected: "NoSuchEntity",
|
||||
},
|
||||
},
|
||||
Logger: c.Config.Logger,
|
||||
NewRequest: func(opts []request.Option) (*request.Request, error) {
|
||||
var inCpy *GetUserInput
|
||||
if input != nil {
|
||||
tmp := *input
|
||||
inCpy = &tmp
|
||||
}
|
||||
req, _ := c.GetUserRequest(inCpy)
|
||||
req.SetContext(ctx)
|
||||
req.ApplyOptions(opts...)
|
||||
return req, nil
|
||||
},
|
||||
}
|
||||
w.ApplyOptions(opts...)
|
||||
|
||||
return w.WaitWithContext(ctx)
|
||||
}
|
|
@ -136,6 +136,7 @@ github.com/aws/aws-sdk-go/private/protocol/xml/xmlutil
|
|||
github.com/aws/aws-sdk-go/service/ec2
|
||||
github.com/aws/aws-sdk-go/service/ec2/ec2iface
|
||||
github.com/aws/aws-sdk-go/service/ecr
|
||||
github.com/aws/aws-sdk-go/service/iam
|
||||
github.com/aws/aws-sdk-go/service/s3
|
||||
github.com/aws/aws-sdk-go/service/s3/s3iface
|
||||
github.com/aws/aws-sdk-go/service/s3/s3manager
|
||||
|
|
|
@ -209,6 +209,30 @@ work, but specifics will depend on your use-case.
|
|||
}
|
||||
```
|
||||
|
||||
In case when you're creating a temporary instance profile you will require to have following
|
||||
IAM policies.
|
||||
|
||||
``` json
|
||||
{
|
||||
"Sid": "PackerIAMCreateRole",
|
||||
"Effect": "Allow",
|
||||
"Action": [
|
||||
"iam:PassRole",
|
||||
"iam:CreateInstanceProfile",
|
||||
"iam:DeleteInstanceProfile",
|
||||
"iam:GetRole",
|
||||
"iam:GetInstanceProfile",
|
||||
"iam:DeleteRolePolicy",
|
||||
"iam:RemoveRoleFromInstanceProfile",
|
||||
"iam:CreateRole",
|
||||
"iam:DeleteRole",
|
||||
"iam:PutRolePolicy",
|
||||
"iam:AddRoleToInstanceProfile"
|
||||
],
|
||||
"Resource": "*"
|
||||
}
|
||||
```
|
||||
|
||||
### Checking that system time is current
|
||||
|
||||
Amazon uses the current time as part of the [request signing
|
||||
|
|
|
@ -64,6 +64,24 @@
|
|||
profile](https://docs.aws.amazon.com/IAM/latest/UserGuide/instance-profiles.html)
|
||||
to launch the EC2 instance with.
|
||||
|
||||
- `temporary_iam_instance_profile_policy_document` (\*PolicyDocument) - Temporary IAM instance profile policy document
|
||||
If IamInstanceProfile is specified it will be used instead. Example:
|
||||
|
||||
```json
|
||||
{
|
||||
"Version": "2012-10-17",
|
||||
"Statement": [
|
||||
{
|
||||
"Action": [
|
||||
"logs:*"
|
||||
],
|
||||
"Effect": "Allow",
|
||||
"Resource": "*"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
- `shutdown_behavior` (string) - Automatically terminate instances on
|
||||
shutdown in case Packer exits ungracefully. Possible values are stop and
|
||||
terminate. Defaults to stop.
|
||||
|
|
Loading…
Reference in New Issue