/
aws.go
155 lines (137 loc) · 4.01 KB
/
aws.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
package main
import (
"math/rand"
"os"
"path"
"strings"
"text/template"
"github.com/aws/aws-sdk-go/aws/credentials"
"github.com/republicprotocol/republic-go/cmd/darknode/config"
"github.com/urfave/cli"
"golang.org/x/crypto/ssh"
)
// All available regions on AWS.
var AllAwsRegions = []string{
"ap-northeast-1",
"ap-northeast-2",
// "ap-northeast-3", awsTerraform having issue support this provider
"ap-south-1",
"ap-southeast-1",
"ap-southeast-2",
"ca-central-1",
"eu-central-1",
"eu-west-1",
"eu-west-2",
"eu-west-3",
"sa-east-1",
"us-east-1",
"us-east-2",
"us-west-1",
"us-west-2",
}
// awsDeployment parses the AWS credentials and use terraform to deploy the
// node to AWS.
func awsDeployment(ctx *cli.Context) error {
region := strings.ToLower(ctx.String("aws-region"))
instance := strings.ToLower(ctx.String("aws-instance"))
if region == "" {
region = AllAwsRegions[rand.Intn(len(AllAwsRegions))]
}
accessKey, secretKey, err := awsCredentials(ctx)
if err != nil {
return err
}
network := ctx.String("network")
network = strings.ToLower(network)
if network != "testnet" && network != "mainnet" {
return ErrUnknownNetwork
}
// Create node directory
name := ctx.String("name")
tags := ctx.String("tags")
if err := mkdir(name, tags); err != nil {
return err
}
nodePath := nodePath(name)
// Generate config and ssh key for the node
config, err := GetConfigOrGenerateNew(ctx, nodePath)
if err != nil {
return err
}
rsaKey := config.Keystore.RsaKey
if err := WriteSshKey(rsaKey.PrivateKey, nodePath); err != nil {
return err
}
pubKey, err := ssh.NewPublicKey(&rsaKey.PublicKey)
if err != nil {
return err
}
// Generate terraform config and start deploying
if err := awsTerraformConfig(ctx, config, pubKey, accessKey, secretKey, region, instance); err != nil {
return err
}
if err := runTerraform(nodePath); err != nil {
return err
}
return outputURL(nodePath, name, network, pubKey.Marshal())
}
// awsCredentials tries to get the AWS credentials from the user input
// or from the default aws credential file
func awsCredentials(ctx *cli.Context) (string, string, error) {
profile := ctx.String("aws-profile")
accessKey := ctx.String("aws-access-key")
secretKey := ctx.String("aws-secret-key")
// Try reading the credential files if user does not provide them directly
if accessKey == "" || secretKey == "" {
creds := credentials.NewSharedCredentials("", profile)
credValue, err := creds.Get()
if err != nil {
return "", "", err
}
accessKey, secretKey = credValue.AccessKeyID, credValue.SecretAccessKey
if accessKey == "" || secretKey == "" {
return "", "", ErrKeyNotFound
}
}
return accessKey, secretKey, nil
}
// awsTerraform contains all the fields needed to generate a terraform config file
// so that we can deploy the node on AWS.
type awsTerraform struct {
Name string
Region string
Address string
InstanceType string
SshPubKey string
SshPriKeyPath string
AccessKey string
SecretKey string
Port string
Path string
AllocationID string
}
// awsTerraformConfig generates the terraform config file for deploying to AWS.
func awsTerraformConfig(ctx *cli.Context, config config.Config, key ssh.PublicKey, accessKey, secretKey, region, instance string) error {
name := ctx.String("name")
nodePath := nodePath(name)
tf := awsTerraform{
Name: name,
Region: region,
Address: config.Address.String(),
InstanceType: instance,
SshPubKey: strings.TrimSpace(StringfySshPubkey(key)),
SshPriKeyPath: path.Join(nodePath, "ssh_keypair"),
AccessKey: accessKey,
SecretKey: secretKey,
Port: config.Port,
Path: Directory,
AllocationID: ctx.String("aws-elastic-ip"),
}
templateFile := path.Join(Directory, "instance", "aws", "aws.tmpl")
t := template.Must(template.New("aws.tmpl").Funcs(template.FuncMap{}).ParseFiles(templateFile))
tfFile, err := os.Create(path.Join(nodePath, "main.tf"))
if err != nil {
return err
}
return t.Execute(tfFile, tf)
}