diff --git a/pkg/model/sshkey.go b/pkg/model/sshkey.go index d173cb6a90..7558a650f7 100644 --- a/pkg/model/sshkey.go +++ b/pkg/model/sshkey.go @@ -37,7 +37,9 @@ func (b *SSHKeyModelBuilder) Build(c *fi.ModelBuilderContext) error { t := &awstasks.SSHKey{ Name: s(name), Lifecycle: b.Lifecycle, - PublicKey: fi.WrapResource(fi.NewStringResource(string(b.SSHPublicKeys[0]))), + } + if len(b.SSHPublicKeys) >= 1 { + t.PublicKey = fi.WrapResource(fi.NewStringResource(string(b.SSHPublicKeys[0]))) } c.AddTask(t) diff --git a/upup/pkg/fi/cloudup/apply_cluster.go b/upup/pkg/fi/cloudup/apply_cluster.go index 9859da4fbe..5bf281078c 100644 --- a/upup/pkg/fi/cloudup/apply_cluster.go +++ b/upup/pkg/fi/cloudup/apply_cluster.go @@ -441,13 +441,13 @@ func (c *ApplyClusterCmd) Run() error { "spotinstElastigroup": &spotinsttasks.Elastigroup{}, }) - if len(sshPublicKeys) == 0 { + if len(sshPublicKeys) == 0 && c.Cluster.Spec.SSHKeyName == "" { return fmt.Errorf("SSH public key must be specified when running with AWS (create with `kops create secret --name %s sshpublickey admin -i ~/.ssh/id_rsa.pub`)", cluster.ObjectMeta.Name) } modelContext.SSHPublicKeys = sshPublicKeys - if len(sshPublicKeys) != 1 { + if len(sshPublicKeys) > 1 { return fmt.Errorf("Exactly one 'admin' SSH public key can be specified when running with AWS; please delete a key using `kops delete secret`") } diff --git a/upup/pkg/fi/cloudup/awstasks/launchtemplate_target_terraform_test.go b/upup/pkg/fi/cloudup/awstasks/launchtemplate_target_terraform_test.go index dfda1dd430..4731dbcd1d 100644 --- a/upup/pkg/fi/cloudup/awstasks/launchtemplate_target_terraform_test.go +++ b/upup/pkg/fi/cloudup/awstasks/launchtemplate_target_terraform_test.go @@ -38,7 +38,8 @@ func TestLaunchTemplateTerraformRender(t *testing.T) { RootVolumeIops: fi.Int64(100), RootVolumeSize: fi.Int64(64), SSHKey: &SSHKey{ - Name: fi.String("mykey"), + Name: fi.String("newkey"), + PublicKey: fi.WrapResource(fi.NewStringResource("newkey")), }, SecurityGroups: []*SecurityGroup{ {Name: fi.String("nodes-1"), ID: fi.String("1111")}, @@ -64,7 +65,7 @@ resource "aws_launch_template" "test" { } instance_type = "t2.medium" - key_name = "${aws_key_pair.mykey.id}" + key_name = "${aws_key_pair.newkey.id}" network_interfaces = { associate_public_ip_address = true @@ -141,7 +142,7 @@ resource "aws_launch_template" "test" { } instance_type = "t2.medium" - key_name = "${aws_key_pair.mykey.id}" + key_name = "mykey" network_interfaces = { associate_public_ip_address = true diff --git a/upup/pkg/fi/cloudup/awstasks/sshkey.go b/upup/pkg/fi/cloudup/awstasks/sshkey.go index c734cab4b3..7fc4c4e82b 100644 --- a/upup/pkg/fi/cloudup/awstasks/sshkey.go +++ b/upup/pkg/fi/cloudup/awstasks/sshkey.go @@ -108,6 +108,16 @@ func (e *SSHKey) Run(c *fi.Context) error { } glog.V(2).Infof("Computed SSH key fingerprint as %q", keyFingerprint) e.KeyFingerprint = &keyFingerprint + } else if e.IsExistingKey() && *e.Name != "" { + a, err := e.Find(c) + if err != nil { + return err + } + if a == nil { + return fmt.Errorf("unable to find specified SSH key %q", *e.Name) + } + + e.KeyFingerprint = a.KeyFingerprint } return fi.DefaultDeltaRunMethod(e, c) } @@ -161,6 +171,10 @@ type terraformSSHKey struct { } func (_ *SSHKey) RenderTerraform(t *terraform.TerraformTarget, a, e, changes *SSHKey) error { + // We don't want to render a key definition when we're using one that already exists + if e.IsExistingKey() { + return nil + } tfName := strings.Replace(*e.Name, ":", "", -1) publicKey, err := t.AddFile("aws_key_pair", tfName, "public_key", e.PublicKey) if err != nil { @@ -175,7 +189,16 @@ func (_ *SSHKey) RenderTerraform(t *terraform.TerraformTarget, a, e, changes *SS return t.RenderResource("aws_key_pair", tfName, tf) } +// IsExistingKey will be true if the task has been initialized without using a public key +// this is when we want to use a key that is already present in AWS. +func (e *SSHKey) IsExistingKey() bool { + return e.PublicKey == nil +} + func (e *SSHKey) TerraformLink() *terraform.Literal { + if e.IsExistingKey() { + return terraform.LiteralFromStringValue(*e.Name) + } tfName := strings.Replace(*e.Name, ":", "", -1) return terraform.LiteralProperty("aws_key_pair", tfName, "id") }