diff --git a/go.mod b/go.mod index 62e4588..d447fb1 100644 --- a/go.mod +++ b/go.mod @@ -56,5 +56,6 @@ require ( golang.org/x/sys v0.19.0 // indirect golang.org/x/text v0.14.0 // indirect golang.org/x/tools v0.17.0 // indirect + gopkg.in/ini.v1 v1.67.0 gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/go.sum b/go.sum index 72e2d7b..ce30255 100644 --- a/go.sum +++ b/go.sum @@ -124,6 +124,8 @@ google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqw gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA= +gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/square/go-jose.v2 v2.6.0 h1:NGk74WTnPKBNUhNzQX7PYcTLUjoq7mzKk2OKbvwk2iI= gopkg.in/square/go-jose.v2 v2.6.0/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= diff --git a/pkg/aws/consts/consts.go b/pkg/aws/consts/consts.go index 42c737a..c413089 100644 --- a/pkg/aws/consts/consts.go +++ b/pkg/aws/consts/consts.go @@ -49,10 +49,10 @@ const ( QEFlagKey = "ocm_ci_flag" // Proxy related - ProxyName = "ocm-proxy" - InstanceKeyName = "openshift-qe" - AWSInstanceUser = "ec2-user" - BastionName = "ocm-bastion" + ProxyName = "ocm-proxy" + InstanceKeyNamePrefix = "ocm-ci" + AWSInstanceUser = "ec2-user" + BastionName = "ocm-bastion" ) var ProxyImageMap = map[string]string{ diff --git a/pkg/file/file.go b/pkg/file/file.go new file mode 100644 index 0000000..6266b04 --- /dev/null +++ b/pkg/file/file.go @@ -0,0 +1,39 @@ +package file + +import ( + "fmt" + "os" + + "github.com/openshift-online/ocm-common/pkg/log" +) + +func WriteToFile(content string, fileName string, path ...string) (string, error) { + KeyPath, _ := os.UserHomeDir() + + if len(path) != 0 { + KeyPath = path[0] + } + + filePath := fmt.Sprintf("%s/%s", KeyPath, fileName) + if IfFileExists(filePath) { + err := os.Remove(filePath) + if err != nil { + log.LogInfo("Delete file err:%v", err) + return "", err + } + } + err := os.WriteFile(filePath, []byte(content), 0600) + if err != nil { + log.LogInfo("Write to file err:%v", err) + return "", err + } + return filePath, nil +} + +func IfFileExists(path string) bool { + _, err := os.Stat(path) + if err != nil { + return os.IsExist(err) + } + return true +} diff --git a/pkg/test/vpc_client/bastion.go b/pkg/test/vpc_client/bastion.go index 7dc98eb..6069012 100644 --- a/pkg/test/vpc_client/bastion.go +++ b/pkg/test/vpc_client/bastion.go @@ -33,7 +33,13 @@ func (vpc *VPC) LaunchBastion(imageID string, zone string) (*types.Instance, err return inst, err } - instOut, err := vpc.AWSClient.LaunchInstance(pubSubnet.ID, imageID, 1, "t3.medium", CON.InstanceKeyName, []string{SGID}, true) + key, err := vpc.CreateKeyPair(fmt.Sprintf("%s-bastion", CON.InstanceKeyNamePrefix)) + if err != nil { + log.LogError("Create key pair failed %s", err) + return inst, err + } + instOut, err := vpc.AWSClient.LaunchInstance(pubSubnet.ID, imageID, 1, "t3.medium", *key.KeyName, []string{SGID}, true) + if err != nil { log.LogError("Launch bastion instance failed %s", err) return inst, err diff --git a/pkg/test/vpc_client/instance.go b/pkg/test/vpc_client/instance.go index c816dd7..2b01b29 100644 --- a/pkg/test/vpc_client/instance.go +++ b/pkg/test/vpc_client/instance.go @@ -30,8 +30,10 @@ func (vpc *VPC) TerminateVPCInstances(nonClusterOnly bool) error { return err } needTermination := []string{} + keyPairNames := []string{} for _, inst := range insts { needTermination = append(needTermination, *inst.InstanceId) + keyPairNames = append(keyPairNames, *inst.KeyName) } err = vpc.AWSClient.TerminateInstances(needTermination, true, 20) if err != nil { @@ -39,6 +41,10 @@ func (vpc *VPC) TerminateVPCInstances(nonClusterOnly bool) error { } else { log.LogInfo("Terminating instances %s successfully", strings.Join(needTermination, ",")) } + err = vpc.DeleteKeyPair(keyPairNames) + if err != nil { + log.LogError("Delete key pair %s meet error: %s", strings.Join(keyPairNames, ","), err) + } return err } diff --git a/pkg/test/vpc_client/key_pair.go b/pkg/test/vpc_client/key_pair.go index d06efda..abb9b81 100644 --- a/pkg/test/vpc_client/key_pair.go +++ b/pkg/test/vpc_client/key_pair.go @@ -1,24 +1,26 @@ package vpc_client import ( + "github.com/aws/aws-sdk-go-v2/service/ec2" "github.com/openshift-online/ocm-common/pkg/log" ) -func (vpc *VPC) CreateKeyPair(keyName string) (*string, error) { +func (vpc *VPC) CreateKeyPair(keyName string) (*ec2.CreateKeyPairOutput, error) { output, err := vpc.AWSClient.CreateKeyPair(keyName) if err != nil { return nil, err } log.LogInfo("create key pair: %v successfully\n", *output.KeyPairId) - content := output.KeyMaterial - return content, nil + return output, nil } -func (vpc *VPC) DeleteKeyPair(keyName string) error { - _, err := vpc.AWSClient.DeleteKeyPair(keyName) - if err != nil { - return err +func (vpc *VPC) DeleteKeyPair(keyNames []string) error { + for _, key := range keyNames { + _, err := vpc.AWSClient.DeleteKeyPair(key) + if err != nil { + return err + } } log.LogInfo("delete key pair successfully\n") return nil diff --git a/pkg/test/vpc_client/proxy.go b/pkg/test/vpc_client/proxy.go index 6d5094b..5b5b304 100644 --- a/pkg/test/vpc_client/proxy.go +++ b/pkg/test/vpc_client/proxy.go @@ -7,13 +7,14 @@ import ( "github.com/aws/aws-sdk-go-v2/service/ec2/types" CON "github.com/openshift-online/ocm-common/pkg/aws/consts" + "github.com/openshift-online/ocm-common/pkg/file" "github.com/openshift-online/ocm-common/pkg/log" ) // LaunchProxyInstance will launch a proxy instance on the indicated zone. // If set imageID to empty, it will find the proxy image in the ProxyImageMap map // LaunchProxyInstance will return proxyInstance detail, privateIPAddress,CAcontent and error -func (vpc *VPC) LaunchProxyInstance(imageID string, zone string, sshKey string) (types.Instance, string, string, error) { +func (vpc *VPC) LaunchProxyInstance(imageID string, zone string, keypairName string, privateKeyPath string) (in types.Instance, privateIP string, proxyServerCA string, err error) { var inst types.Instance if imageID == "" { var ok bool @@ -46,20 +47,40 @@ func (vpc *VPC) LaunchProxyInstance(imageID string, zone string, sshKey string) return inst, "", "", err } - instOut, err := vpc.AWSClient.LaunchInstance(pubSubnet.ID, imageID, 1, "t3.medium", CON.InstanceKeyName, []string{SGID}, true) + keyName := fmt.Sprintf("%s-%s", CON.InstanceKeyNamePrefix, keypairName) + key, err := vpc.CreateKeyPair(keyName) if err != nil { - log.LogError("Launch proxy instance failed %s", err) + log.LogError("Create key pair %s failed %s", keyName, err) return inst, "", "", err - } else { - log.LogInfo("Launch proxy instance %s succeed", *instOut.Instances[0].InstanceId) } tags := map[string]string{ "Name": CON.ProxyName, } + _, err = vpc.AWSClient.TagResource(*key.KeyPairId, tags) + if err != nil { + log.LogError("Add tag for key pair %s failed %s", *key.KeyPairId, err) + return inst, "", "", err + } + privateKeyName := fmt.Sprintf("%s-%s", keypairName, "keyPair.pem") + sshKey, err := file.WriteToFile(*key.KeyMaterial, privateKeyName, privateKeyPath) + if err != nil { + log.LogError("Write private key to file failed %s", err) + return inst, "", "", err + } + + instOut, err := vpc.AWSClient.LaunchInstance(pubSubnet.ID, imageID, 1, "t3.medium", keyName, []string{SGID}, true) + if err != nil { + log.LogError("Launch proxy instance failed %s", err) + return inst, "", "", err + } else { + log.LogInfo("Launch proxy instance %s succeed", *instOut.Instances[0].InstanceId) + } + instID := *instOut.Instances[0].InstanceId _, err = vpc.AWSClient.TagResource(instID, tags) if err != nil { - return inst, "", "", fmt.Errorf("tag instance %s failed:%s", instID, err) + log.LogError("Add tag for instance %s failed %s", instID, err) + return inst, "", "", err } publicIP, err := vpc.AWSClient.AllocateEIPAndAssociateInstance(instID) @@ -83,7 +104,6 @@ func (vpc *VPC) LaunchProxyInstance(imageID string, zone string, sshKey string) log.LogError("login instance to run cmd %s failed %s", cmd2, err) return inst, "", "", err } - return instOut.Instances[0], *instOut.Instances[0].PrivateIpAddress, caContent, err }