From 8c87b1cc00618632ef1a80e4d349e2918bf92c8b Mon Sep 17 00:00:00 2001 From: "Lesko, Matthew (NIH/NLM/NCBI) [C]" Date: Tue, 13 Jan 2015 12:20:31 -0500 Subject: [PATCH 1/4] First attempt for re-using a named EC2 keypair Adds a 'ssh_keypair_name' option to the configuration for AWS, along with some munging to create the temporarily keypair if one isn't specific. NOT YET WORKING. From a 'make' I get the following errors: builder/amazon/ebs/builder.go:94: b.config.SSHKeyPairName undefined (type config has no field or method SSHKeyPairName) builder/amazon/instance/builder.go:199: b.config.SSHKeyPairName undefined (type Config has no field or method SSHKeyPairName) --- builder/amazon/common/run_config.go | 7 +++++-- builder/amazon/common/run_config_test.go | 4 ++-- builder/amazon/common/step_key_pair.go | 22 ++++++++++++---------- builder/amazon/ebs/builder.go | 2 +- builder/amazon/instance/builder.go | 2 +- 5 files changed, 21 insertions(+), 16 deletions(-) diff --git a/builder/amazon/common/run_config.go b/builder/amazon/common/run_config.go index a71387623..f6e859c03 100644 --- a/builder/amazon/common/run_config.go +++ b/builder/amazon/common/run_config.go @@ -24,6 +24,7 @@ type RunConfig struct { RawSSHTimeout string `mapstructure:"ssh_timeout"` SSHUsername string `mapstructure:"ssh_username"` SSHPrivateKeyFile string `mapstructure:"ssh_private_key_file"` + SSHKeyPairName string `mapstructure:"ssh_keypair_name"` SSHPrivateIp bool `mapstructure:"ssh_private_ip"` SSHPort int `mapstructure:"ssh_port"` SecurityGroupId string `mapstructure:"security_group_id"` @@ -55,6 +56,7 @@ func (c *RunConfig) Prepare(t *packer.ConfigTemplate) []error { "ssh_timeout": &c.RawSSHTimeout, "ssh_username": &c.SSHUsername, "ssh_private_key_file": &c.SSHPrivateKeyFile, + "ssh_keypair_name": &c.SSHKeyPairName, "source_ami": &c.SourceAmi, "subnet_id": &c.SubnetId, "temporary_key_pair_name": &c.TemporaryKeyPairName, @@ -84,8 +86,9 @@ func (c *RunConfig) Prepare(t *packer.ConfigTemplate) []error { c.RawSSHTimeout = "5m" } - if c.TemporaryKeyPairName == "" { - c.TemporaryKeyPairName = fmt.Sprintf( + // if we are not given an explicit keypairname, create a temporary one + if c.SSHKeyPairName == "" { + c.SSHKeyPairName = fmt.Sprintf( "packer %s", uuid.TimeOrderedUUID()) } diff --git a/builder/amazon/common/run_config_test.go b/builder/amazon/common/run_config_test.go index 8e9c4b6b9..c4e1fa110 100644 --- a/builder/amazon/common/run_config_test.go +++ b/builder/amazon/common/run_config_test.go @@ -142,12 +142,12 @@ func TestRunConfigPrepare_UserDataFile(t *testing.T) { func TestRunConfigPrepare_TemporaryKeyPairName(t *testing.T) { c := testConfig() - c.TemporaryKeyPairName = "" + c.SSHKeyPairName = "" if err := c.Prepare(nil); len(err) != 0 { t.Fatalf("err: %s", err) } - if c.TemporaryKeyPairName == "" { + if c.SSHKeyPairName == "" { t.Fatal("keypair empty") } } diff --git a/builder/amazon/common/step_key_pair.go b/builder/amazon/common/step_key_pair.go index 3a7eb9f35..db60e1e40 100644 --- a/builder/amazon/common/step_key_pair.go +++ b/builder/amazon/common/step_key_pair.go @@ -21,7 +21,7 @@ type StepKeyPair struct { func (s *StepKeyPair) Run(state multistep.StateBag) multistep.StepAction { if s.PrivateKeyFile != "" { - s.keyName = "" + s.keyName = s.KeyPairName // need to get from config privateKeyBytes, err := ioutil.ReadFile(s.PrivateKeyFile) if err != nil { @@ -29,7 +29,7 @@ func (s *StepKeyPair) Run(state multistep.StateBag) multistep.StepAction { return multistep.ActionHalt } - state.Put("keyPair", "") + state.Put("keyPair", s.keyName) state.Put("privateKey", string(privateKeyBytes)) return multistep.ActionContinue @@ -83,17 +83,19 @@ func (s *StepKeyPair) Run(state multistep.StateBag) multistep.StepAction { func (s *StepKeyPair) Cleanup(state multistep.StateBag) { // If no key name is set, then we never created it, so just return - if s.keyName == "" { + // If we used an SSH private key file, do not go about deleting + // keypairs + if s.PrivateKeyFile != "" { return } - ec2conn := state.Get("ec2").(*ec2.EC2) + //ec2conn := state.Get("ec2").(*ec2.EC2) ui := state.Get("ui").(packer.Ui) - ui.Say("Deleting temporary keypair...") - _, err := ec2conn.DeleteKeyPair(s.keyName) - if err != nil { - ui.Error(fmt.Sprintf( - "Error cleaning up keypair. Please delete the key manually: %s", s.keyName)) - } + ui.Say("DANGER: Deleting temporary keypair (not really)...") + //_, err := ec2conn.DeleteKeyPair(s.keyName) + //if err != nil { + //ui.Error(fmt.Sprintf( + //"Error cleaning up keypair. Please delete the key manually: %s", s.keyName)) + //} } diff --git a/builder/amazon/ebs/builder.go b/builder/amazon/ebs/builder.go index 889cc7b60..083507993 100644 --- a/builder/amazon/ebs/builder.go +++ b/builder/amazon/ebs/builder.go @@ -91,7 +91,7 @@ func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packe &awscommon.StepKeyPair{ Debug: b.config.PackerDebug, DebugKeyPath: fmt.Sprintf("ec2_%s.pem", b.config.PackerBuildName), - KeyPairName: b.config.TemporaryKeyPairName, + KeyPairName: b.config.SSHKeyPairName, PrivateKeyFile: b.config.SSHPrivateKeyFile, }, &awscommon.StepSecurityGroup{ diff --git a/builder/amazon/instance/builder.go b/builder/amazon/instance/builder.go index 1f5c1d9c8..ce582e039 100644 --- a/builder/amazon/instance/builder.go +++ b/builder/amazon/instance/builder.go @@ -196,7 +196,7 @@ func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packe &awscommon.StepKeyPair{ Debug: b.config.PackerDebug, DebugKeyPath: fmt.Sprintf("ec2_%s.pem", b.config.PackerBuildName), - KeyPairName: b.config.TemporaryKeyPairName, + KeyPairName: b.config.SSHKeyPairName, PrivateKeyFile: b.config.SSHPrivateKeyFile, }, &awscommon.StepSecurityGroup{ From 9d097f9d4ef331adac5f322d14ca185e879331a0 Mon Sep 17 00:00:00 2001 From: "Lesko, Matthew (NIH/NLM/NCBI) [C]" Date: Tue, 13 Jan 2015 16:27:33 -0500 Subject: [PATCH 2/4] Permit Temp keys and named SSH keypairs These changes permit the use of pre-created SSH keypairs with AWS. If so, the configuration for the builder needs to include an ssh_keypair_name option and a ssh_private_key_file. If ssh_private_key_file is *not* defined, it'll go through the rigamarole of creating a temporary keypair. The ssh_keypair_name option by itself won't make that change, because it doesn't make sense to specify a keypair but not tell packer where the private key is, but it does happen that you could have a private key and the public-key is "baked in", and not part of your EC2 account. --- builder/amazon/common/run_config.go | 2 +- builder/amazon/common/run_config_test.go | 4 ++-- builder/amazon/common/step_key_pair.go | 25 +++++++++++++----------- builder/amazon/ebs/builder.go | 9 +++++---- builder/amazon/instance/builder.go | 9 +++++---- 5 files changed, 27 insertions(+), 22 deletions(-) diff --git a/builder/amazon/common/run_config.go b/builder/amazon/common/run_config.go index f6e859c03..67ec74d79 100644 --- a/builder/amazon/common/run_config.go +++ b/builder/amazon/common/run_config.go @@ -88,7 +88,7 @@ func (c *RunConfig) Prepare(t *packer.ConfigTemplate) []error { // if we are not given an explicit keypairname, create a temporary one if c.SSHKeyPairName == "" { - c.SSHKeyPairName = fmt.Sprintf( + c.TemporaryKeyPairName = fmt.Sprintf( "packer %s", uuid.TimeOrderedUUID()) } diff --git a/builder/amazon/common/run_config_test.go b/builder/amazon/common/run_config_test.go index c4e1fa110..8e9c4b6b9 100644 --- a/builder/amazon/common/run_config_test.go +++ b/builder/amazon/common/run_config_test.go @@ -142,12 +142,12 @@ func TestRunConfigPrepare_UserDataFile(t *testing.T) { func TestRunConfigPrepare_TemporaryKeyPairName(t *testing.T) { c := testConfig() - c.SSHKeyPairName = "" + c.TemporaryKeyPairName = "" if err := c.Prepare(nil); len(err) != 0 { t.Fatalf("err: %s", err) } - if c.SSHKeyPairName == "" { + if c.TemporaryKeyPairName == "" { t.Fatal("keypair empty") } } diff --git a/builder/amazon/common/step_key_pair.go b/builder/amazon/common/step_key_pair.go index db60e1e40..f6e6a0555 100644 --- a/builder/amazon/common/step_key_pair.go +++ b/builder/amazon/common/step_key_pair.go @@ -13,6 +13,7 @@ import ( type StepKeyPair struct { Debug bool DebugKeyPath string + TemporaryKeyPairName string KeyPairName string PrivateKeyFile string @@ -21,7 +22,9 @@ type StepKeyPair struct { func (s *StepKeyPair) Run(state multistep.StateBag) multistep.StepAction { if s.PrivateKeyFile != "" { - s.keyName = s.KeyPairName // need to get from config + if s.KeyPairName != "" { + s.keyName = s.KeyPairName // need to get from config + } privateKeyBytes, err := ioutil.ReadFile(s.PrivateKeyFile) if err != nil { @@ -38,15 +41,15 @@ func (s *StepKeyPair) Run(state multistep.StateBag) multistep.StepAction { ec2conn := state.Get("ec2").(*ec2.EC2) ui := state.Get("ui").(packer.Ui) - ui.Say(fmt.Sprintf("Creating temporary keypair: %s", s.KeyPairName)) - keyResp, err := ec2conn.CreateKeyPair(s.KeyPairName) + ui.Say(fmt.Sprintf("Creating temporary keypair: %s", s.TemporaryKeyPairName)) + keyResp, err := ec2conn.CreateKeyPair(s.TemporaryKeyPairName) if err != nil { state.Put("error", fmt.Errorf("Error creating temporary keypair: %s", err)) return multistep.ActionHalt } // Set the keyname so we know to delete it later - s.keyName = s.KeyPairName + s.keyName = s.TemporaryKeyPairName // Set some state data for use in future steps state.Put("keyPair", s.keyName) @@ -89,13 +92,13 @@ func (s *StepKeyPair) Cleanup(state multistep.StateBag) { return } - //ec2conn := state.Get("ec2").(*ec2.EC2) + ec2conn := state.Get("ec2").(*ec2.EC2) ui := state.Get("ui").(packer.Ui) - ui.Say("DANGER: Deleting temporary keypair (not really)...") - //_, err := ec2conn.DeleteKeyPair(s.keyName) - //if err != nil { - //ui.Error(fmt.Sprintf( - //"Error cleaning up keypair. Please delete the key manually: %s", s.keyName)) - //} + ui.Say("DANGER: Deleting temporary keypair...") + _, err := ec2conn.DeleteKeyPair(s.keyName) + if err != nil { + ui.Error(fmt.Sprintf( + "Error cleaning up keypair. Please delete the key manually: %s", s.keyName)) + } } diff --git a/builder/amazon/ebs/builder.go b/builder/amazon/ebs/builder.go index 083507993..95e7ea016 100644 --- a/builder/amazon/ebs/builder.go +++ b/builder/amazon/ebs/builder.go @@ -89,10 +89,11 @@ func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packe EnhancedNetworking: b.config.AMIEnhancedNetworking, }, &awscommon.StepKeyPair{ - Debug: b.config.PackerDebug, - DebugKeyPath: fmt.Sprintf("ec2_%s.pem", b.config.PackerBuildName), - KeyPairName: b.config.SSHKeyPairName, - PrivateKeyFile: b.config.SSHPrivateKeyFile, + Debug: b.config.PackerDebug, + DebugKeyPath: fmt.Sprintf("ec2_%s.pem", b.config.PackerBuildName), + TemporaryKeyPairName: b.config.TemporaryKeyPairName, + KeyPairName: b.config.SSHKeyPairName, + PrivateKeyFile: b.config.SSHPrivateKeyFile, }, &awscommon.StepSecurityGroup{ SecurityGroupIds: b.config.SecurityGroupIds, diff --git a/builder/amazon/instance/builder.go b/builder/amazon/instance/builder.go index ce582e039..b677f4da9 100644 --- a/builder/amazon/instance/builder.go +++ b/builder/amazon/instance/builder.go @@ -194,10 +194,11 @@ func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packe EnhancedNetworking: b.config.AMIEnhancedNetworking, }, &awscommon.StepKeyPair{ - Debug: b.config.PackerDebug, - DebugKeyPath: fmt.Sprintf("ec2_%s.pem", b.config.PackerBuildName), - KeyPairName: b.config.SSHKeyPairName, - PrivateKeyFile: b.config.SSHPrivateKeyFile, + Debug: b.config.PackerDebug, + DebugKeyPath: fmt.Sprintf("ec2_%s.pem", b.config.PackerBuildName), + TemporaryKeyPairName: b.config.TemporaryKeyPairName, + KeyPairName: b.config.SSHKeyPairName, + PrivateKeyFile: b.config.SSHPrivateKeyFile, }, &awscommon.StepSecurityGroup{ SecurityGroupIds: b.config.SecurityGroupIds, From 62e054c404e7e622203a5aadb9e062c77c663d87 Mon Sep 17 00:00:00 2001 From: "Lesko, Matthew (NIH/NLM/NCBI) [C]" Date: Tue, 13 Jan 2015 21:40:15 -0500 Subject: [PATCH 3/4] simplify output --- builder/amazon/common/step_key_pair.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/builder/amazon/common/step_key_pair.go b/builder/amazon/common/step_key_pair.go index f6e6a0555..a4baf8e0b 100644 --- a/builder/amazon/common/step_key_pair.go +++ b/builder/amazon/common/step_key_pair.go @@ -95,7 +95,7 @@ func (s *StepKeyPair) Cleanup(state multistep.StateBag) { ec2conn := state.Get("ec2").(*ec2.EC2) ui := state.Get("ui").(packer.Ui) - ui.Say("DANGER: Deleting temporary keypair...") + ui.Say("Deleting temporary keypair...") _, err := ec2conn.DeleteKeyPair(s.keyName) if err != nil { ui.Error(fmt.Sprintf( From 43f08b2664d9736a71152e0bd0df397f994e6afe Mon Sep 17 00:00:00 2001 From: "Lesko, Matthew (NIH/NLM/NCBI) [C]" Date: Tue, 13 Jan 2015 22:58:41 -0500 Subject: [PATCH 4/4] go fmt all the things --- builder/amazon/common/run_config.go | 2 +- builder/amazon/common/step_key_pair.go | 24 ++++++++++++------------ builder/amazon/ebs/builder.go | 2 +- builder/amazon/instance/builder.go | 2 +- 4 files changed, 15 insertions(+), 15 deletions(-) diff --git a/builder/amazon/common/run_config.go b/builder/amazon/common/run_config.go index 67ec74d79..d4ebec0e1 100644 --- a/builder/amazon/common/run_config.go +++ b/builder/amazon/common/run_config.go @@ -87,7 +87,7 @@ func (c *RunConfig) Prepare(t *packer.ConfigTemplate) []error { } // if we are not given an explicit keypairname, create a temporary one - if c.SSHKeyPairName == "" { + if c.SSHKeyPairName == "" { c.TemporaryKeyPairName = fmt.Sprintf( "packer %s", uuid.TimeOrderedUUID()) } diff --git a/builder/amazon/common/step_key_pair.go b/builder/amazon/common/step_key_pair.go index a4baf8e0b..3f40e3d77 100644 --- a/builder/amazon/common/step_key_pair.go +++ b/builder/amazon/common/step_key_pair.go @@ -11,20 +11,20 @@ import ( ) type StepKeyPair struct { - Debug bool - DebugKeyPath string - TemporaryKeyPairName string - KeyPairName string - PrivateKeyFile string + Debug bool + DebugKeyPath string + TemporaryKeyPairName string + KeyPairName string + PrivateKeyFile string keyName string } func (s *StepKeyPair) Run(state multistep.StateBag) multistep.StepAction { if s.PrivateKeyFile != "" { - if s.KeyPairName != "" { - s.keyName = s.KeyPairName // need to get from config - } + if s.KeyPairName != "" { + s.keyName = s.KeyPairName // need to get from config + } privateKeyBytes, err := ioutil.ReadFile(s.PrivateKeyFile) if err != nil { @@ -86,8 +86,8 @@ func (s *StepKeyPair) Run(state multistep.StateBag) multistep.StepAction { func (s *StepKeyPair) Cleanup(state multistep.StateBag) { // If no key name is set, then we never created it, so just return - // If we used an SSH private key file, do not go about deleting - // keypairs + // If we used an SSH private key file, do not go about deleting + // keypairs if s.PrivateKeyFile != "" { return } @@ -98,7 +98,7 @@ func (s *StepKeyPair) Cleanup(state multistep.StateBag) { ui.Say("Deleting temporary keypair...") _, err := ec2conn.DeleteKeyPair(s.keyName) if err != nil { - ui.Error(fmt.Sprintf( - "Error cleaning up keypair. Please delete the key manually: %s", s.keyName)) + ui.Error(fmt.Sprintf( + "Error cleaning up keypair. Please delete the key manually: %s", s.keyName)) } } diff --git a/builder/amazon/ebs/builder.go b/builder/amazon/ebs/builder.go index 95e7ea016..0c2258ad6 100644 --- a/builder/amazon/ebs/builder.go +++ b/builder/amazon/ebs/builder.go @@ -91,7 +91,7 @@ func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packe &awscommon.StepKeyPair{ Debug: b.config.PackerDebug, DebugKeyPath: fmt.Sprintf("ec2_%s.pem", b.config.PackerBuildName), - TemporaryKeyPairName: b.config.TemporaryKeyPairName, + TemporaryKeyPairName: b.config.TemporaryKeyPairName, KeyPairName: b.config.SSHKeyPairName, PrivateKeyFile: b.config.SSHPrivateKeyFile, }, diff --git a/builder/amazon/instance/builder.go b/builder/amazon/instance/builder.go index b677f4da9..538e9efb7 100644 --- a/builder/amazon/instance/builder.go +++ b/builder/amazon/instance/builder.go @@ -196,7 +196,7 @@ func (b *Builder) Run(ui packer.Ui, hook packer.Hook, cache packer.Cache) (packe &awscommon.StepKeyPair{ Debug: b.config.PackerDebug, DebugKeyPath: fmt.Sprintf("ec2_%s.pem", b.config.PackerBuildName), - TemporaryKeyPairName: b.config.TemporaryKeyPairName, + TemporaryKeyPairName: b.config.TemporaryKeyPairName, KeyPairName: b.config.SSHKeyPairName, PrivateKeyFile: b.config.SSHPrivateKeyFile, },