From 8701b8ff61f8ce358b9ff9d7e6f26da97bb9a6e7 Mon Sep 17 00:00:00 2001 From: LilyFaFa <21621231@zju.edu.cn> Date: Sun, 20 May 2018 18:55:09 +0800 Subject: [PATCH] implement SSHKey task for ALICloud --- upup/pkg/fi/cloudup/alitasks/BUILD.bazel | 2 + upup/pkg/fi/cloudup/alitasks/sshkey.go | 140 ++++++++++++++++++ upup/pkg/fi/cloudup/alitasks/sshkey_fitask.go | 75 ++++++++++ 3 files changed, 217 insertions(+) create mode 100644 upup/pkg/fi/cloudup/alitasks/sshkey.go create mode 100644 upup/pkg/fi/cloudup/alitasks/sshkey_fitask.go diff --git a/upup/pkg/fi/cloudup/alitasks/BUILD.bazel b/upup/pkg/fi/cloudup/alitasks/BUILD.bazel index 4d46ba2fac14b..e6414cace5f2c 100644 --- a/upup/pkg/fi/cloudup/alitasks/BUILD.bazel +++ b/upup/pkg/fi/cloudup/alitasks/BUILD.bazel @@ -5,6 +5,8 @@ go_library( srcs = [ "disk.go", "disk_fitask.go", + "sshkey.go", + "sshkey_fitask.go", "vpc.go", "vpc_fitask.go", "vswitch.go", diff --git a/upup/pkg/fi/cloudup/alitasks/sshkey.go b/upup/pkg/fi/cloudup/alitasks/sshkey.go new file mode 100644 index 0000000000000..8ab9e5ca21dbf --- /dev/null +++ b/upup/pkg/fi/cloudup/alitasks/sshkey.go @@ -0,0 +1,140 @@ +/* +Copyright 2018 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package alitasks + +import ( + "fmt" + + common "github.com/denverdino/aliyungo/common" + ecs "github.com/denverdino/aliyungo/ecs" + + "github.com/golang/glog" + "k8s.io/kops/upup/pkg/fi" + "k8s.io/kops/upup/pkg/fi/cloudup/aliup" + "k8s.io/kops/upup/pkg/fi/cloudup/terraform" +) + +//go:generate fitask -type=SSHKey +type SSHKey struct { + Name *string + Lifecycle *fi.Lifecycle + PublicKey *fi.ResourceHolder + KeyPairFingerPrint *string +} + +var _ fi.CompareWithID = &SSHKey{} + +func (s *SSHKey) CompareWithID() *string { + return s.Name +} + +func (s *SSHKey) Find(c *fi.Context) (*SSHKey, error) { + cloud := c.Cloud.(aliup.ALICloud) + + describeKeyPairsArgs := &ecs.DescribeKeyPairsArgs{ + RegionId: common.Region(cloud.Region()), + KeyPairName: fi.StringValue(s.Name), + } + keypairs, _, err := cloud.EcsClient().DescribeKeyPairs(describeKeyPairsArgs) + + if err != nil { + return nil, fmt.Errorf("error listing SSHKeys: %v", err) + } + + if len(keypairs) == 0 { + return nil, nil + } + if len(keypairs) != 1 { + return nil, fmt.Errorf("Found multiple SSHKeys with Name %q", *s.Name) + } + + glog.V(2).Infof("found matching SSHKey with name: %q", *s.Name) + k := keypairs[0] + actual := &SSHKey{ + Name: fi.String(k.KeyPairName), + KeyPairFingerPrint: fi.String(k.KeyPairFingerPrint), + } + // Ignore "system" fields + actual.Lifecycle = s.Lifecycle + + return actual, nil +} + +func (s *SSHKey) Run(c *fi.Context) error { + return fi.DefaultDeltaRunMethod(s, c) +} + +func (s *SSHKey) CheckChanges(a, e, changes *SSHKey) error { + if a != nil { + if changes.Name != nil { + return fi.CannotChangeField("Name") + } + } + return nil +} + +func (_ *SSHKey) RenderALI(t *aliup.ALIAPITarget, a, e, changes *SSHKey) error { + if a == nil { + glog.V(2).Infof("Creating SSHKey with Name:%q", fi.StringValue(e.Name)) + + importKeyPairArgs := &ecs.ImportKeyPairArgs{ + RegionId: common.Region(t.Cloud.Region()), + KeyPairName: fi.StringValue(e.Name), + } + + if e.PublicKey != nil { + d, err := e.PublicKey.AsString() + if err != nil { + return fmt.Errorf("error rendering SSHKey PublicKey: %v", err) + } + importKeyPairArgs.PublicKeyBody = d + } + + importKeyPairResponse, err := t.Cloud.EcsClient().ImportKeyPair(importKeyPairArgs) + if err != nil { + return fmt.Errorf("error creating SSHKey: %v", err) + } + e.KeyPairFingerPrint = fi.String(importKeyPairResponse.KeyPairFingerPrint) + return nil + } + + return nil +} + +type terraformSSHKey struct { + Name *string `json:"key_name,omitempty"` + PublicKey *string `json:"public_key,omitempty"` +} + +func (_ *SSHKey) RenderTerraform(t *terraform.TerraformTarget, a, e, changes *SSHKey) error { + + keyString, err := e.PublicKey.AsString() + if err != nil { + return fmt.Errorf("error rendering SSHKey PublicKey: %v", err) + } + + tf := &terraformSSHKey{ + Name: e.Name, + PublicKey: &keyString, + } + + return t.RenderResource("alicloud_key_pair", *e.Name, tf) +} + +func (s *SSHKey) TerraformLink() *terraform.Literal { + return terraform.LiteralProperty("alicloud_key_pair", *s.Name, "name") +} diff --git a/upup/pkg/fi/cloudup/alitasks/sshkey_fitask.go b/upup/pkg/fi/cloudup/alitasks/sshkey_fitask.go new file mode 100644 index 0000000000000..fe7e4672754ac --- /dev/null +++ b/upup/pkg/fi/cloudup/alitasks/sshkey_fitask.go @@ -0,0 +1,75 @@ +/* +Copyright 2018 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by ""fitask" -type=SSHKey"; DO NOT EDIT + +package alitasks + +import ( + "encoding/json" + + "k8s.io/kops/upup/pkg/fi" +) + +// SSHKey + +// JSON marshalling boilerplate +type realSSHKey SSHKey + +// UnmarshalJSON implements conversion to JSON, supporitng an alternate specification of the object as a string +func (o *SSHKey) UnmarshalJSON(data []byte) error { + var jsonName string + if err := json.Unmarshal(data, &jsonName); err == nil { + o.Name = &jsonName + return nil + } + + var r realSSHKey + if err := json.Unmarshal(data, &r); err != nil { + return err + } + *o = SSHKey(r) + return nil +} + +var _ fi.HasLifecycle = &SSHKey{} + +// GetLifecycle returns the Lifecycle of the object, implementing fi.HasLifecycle +func (o *SSHKey) GetLifecycle() *fi.Lifecycle { + return o.Lifecycle +} + +// SetLifecycle sets the Lifecycle of the object, implementing fi.SetLifecycle +func (o *SSHKey) SetLifecycle(lifecycle fi.Lifecycle) { + o.Lifecycle = &lifecycle +} + +var _ fi.HasName = &SSHKey{} + +// GetName returns the Name of the object, implementing fi.HasName +func (o *SSHKey) GetName() *string { + return o.Name +} + +// SetName sets the Name of the object, implementing fi.SetName +func (o *SSHKey) SetName(name string) { + o.Name = &name +} + +// String is the stringer function for the task, producing readable output using fi.TaskAsString +func (o *SSHKey) String() string { + return fi.TaskAsString(o) +}