Skip to content

Commit 9e893d8

Browse files
authored
Azure provider (#18)
* wip * wip * wip * wip * wipp * wip * wipp * code * pre-release * wip runner * json * wait * base64 * clooud * credentials * remove log * setname * aws delete by tag * same id * install gpu * aws az runner * iterative_cml_runner and cleanup * remove azure
1 parent b16c319 commit 9e893d8

File tree

1,099 files changed

+428379
-18902
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

1,099 files changed

+428379
-18902
lines changed

.gitignore

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
.DS_Store
2-
examples
2+
examples/.terraform
33
bin
44

55
# Local .terraform directories

Makefile

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,11 @@
11
TEST?=$$(go list ./... | grep -v 'vendor')
22
HOSTNAME=github.com
3-
NAMESPACE=DavidGOrtega
3+
NAMESPACE=iterative
44
NAME=iterative
5-
VERSION=0.3
5+
VERSION=0.6
66
#OS_ARCH=linux_amd64
77
OS_ARCH=darwin_amd64
88
BINARY=terraform-provider-${NAME}
9-
VERSION2=0.3.3
109

1110
default: install
1211

cml/ami.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
},
1212
"region" : "us-west-1",
1313
"ami_name" : "iterative-cml",
14-
"ami_description" : "CML (Continous Machine Learning)",
14+
"ami_description" : "CML (Continous Machine Learning). Ubuntu 18.04",
1515
"ami_groups": ["all"],
1616
"force_deregister": "true",
1717
"force_delete_snapshot": "true",

cml/setup.sh

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,22 @@
11
#/bin/sh
22

3+
DEBIAN_FRONTEND=noninteractive
34
echo "APT::Get::Assume-Yes \"true\";" | sudo tee -a /etc/apt/apt.conf.d/90assumeyes
45

5-
curl -fsSL https://get.docker.com -o get-docker.sh && sh get-docker.sh && \
6-
sudo usermod -aG docker \${USER}
7-
sudo setfacl --modify user:\${USER}:rw /var/run/docker.sock
6+
sudo apt update
7+
sudo curl -fsSL https://get.docker.com -o get-docker.sh && sudo sh get-docker.sh && \
8+
sudo usermod -aG docker ubuntu
9+
sudo setfacl --modify user:ubuntu:rw /var/run/docker.sock
810

11+
curl -fsSL https://apt.releases.hashicorp.com/gpg | sudo apt-key add -
12+
sudo apt-add-repository "deb [arch=amd64] https://apt.releases.hashicorp.com $(lsb_release -cs) main"
13+
sudo apt update && sudo apt-get install -y terraform
14+
15+
curl -sL https://deb.nodesource.com/setup_12.x | sudo bash
16+
sudo apt update && sudo apt-get install -y nodejs
17+
18+
sudo apt install -y ubuntu-drivers-common git
19+
sudo ubuntu-drivers autoinstall
920
curl -s -L https://nvidia.GitHub.io/nvidia-docker/gpgkey | sudo apt-key add - && \
10-
curl -s -L https://nvidia.GitHub.io/nvidia-docker/ubuntu18.04/nvidia-docker.list | sudo tee /etc/apt/sources.list.d/nvidia-docker.list && \
11-
sudo apt update && sudo apt install -y ubuntu-drivers-common && \
12-
sudo ubuntu-drivers autoinstall && \
13-
sudo apt install -y nvidia-container-toolkit
21+
curl -s -L https://nvidia.GitHub.io/nvidia-docker/ubuntu18.04/nvidia-docker.list | sudo tee /etc/apt/sources.list.d/nvidia-docker.list
22+
sudo apt update && sudo apt install -y nvidia-container-toolkit

go.mod

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,15 @@ module terraform-provider-iterative
33
go 1.14
44

55
require (
6+
github.com/Azure-Samples/azure-sdk-for-go-samples v0.0.0-20201110054206-ffcdafe9818d // indirect
7+
github.com/Azure/azure-sdk-for-go v49.0.0+incompatible
8+
github.com/Azure/go-autorest/autorest v0.11.13 // indirect
9+
github.com/Azure/go-autorest/autorest/azure/auth v0.5.3
10+
github.com/Azure/go-autorest/autorest/to v0.4.0
611
github.com/aws/aws-sdk-go v1.34.13
7-
github.com/hashicorp/terraform-plugin-sdk/v2 v2.0.1
12+
github.com/hashicorp/terraform v0.14.2
13+
github.com/hashicorp/terraform-plugin-sdk/v2 v2.4.0
814
github.com/teris-io/shortid v0.0.0-20171029131806-771a37caa5cf
15+
github.com/zclconf/go-cty v1.7.0 // indirect
16+
golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0
917
)

go.sum

Lines changed: 457 additions & 19 deletions
Large diffs are not rendered by default.

iterative/aws/provider.go

Lines changed: 285 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,285 @@
1+
package aws
2+
3+
import (
4+
"context"
5+
"errors"
6+
"sort"
7+
"time"
8+
9+
"github.com/aws/aws-sdk-go/aws"
10+
"github.com/aws/aws-sdk-go/aws/session"
11+
"github.com/aws/aws-sdk-go/service/ec2"
12+
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
13+
)
14+
15+
//ResourceMachineCreate creates AWS instance
16+
func ResourceMachineCreate(ctx context.Context, d *schema.ResourceData, m interface{}) error {
17+
userData := d.Get("startup_script").(string)
18+
instanceName := d.Get("name").(string)
19+
pairName := d.Id()
20+
hddSize := d.Get("instance_hdd_size").(int)
21+
region := getRegion(d.Get("region").(string))
22+
instanceType := getInstanceType(d.Get("instance_type").(string), d.Get("instance_gpu").(string))
23+
ami := d.Get("image").(string)
24+
keyPublic := d.Get("ssh_public").(string)
25+
securityGroup := d.Get("aws_security_group").(string)
26+
if ami == "" {
27+
ami = "iterative-cml"
28+
}
29+
30+
svc, err := awsClient(region)
31+
if err != nil {
32+
return err
33+
}
34+
35+
// Image
36+
imagesRes, err := svc.DescribeImages(&ec2.DescribeImagesInput{
37+
Filters: []*ec2.Filter{
38+
{
39+
Name: aws.String("name"),
40+
Values: []*string{aws.String(ami)},
41+
},
42+
{
43+
Name: aws.String("architecture"),
44+
Values: []*string{aws.String("x86_64")},
45+
},
46+
},
47+
})
48+
if err != nil {
49+
return err
50+
}
51+
if len(imagesRes.Images) == 0 {
52+
return errors.New(ami + " ami not found in region")
53+
}
54+
55+
sort.Slice(imagesRes.Images, func(i, j int) bool {
56+
itime, _ := time.Parse(time.RFC3339, aws.StringValue(imagesRes.Images[i].CreationDate))
57+
jtime, _ := time.Parse(time.RFC3339, aws.StringValue(imagesRes.Images[j].CreationDate))
58+
return itime.Unix() > jtime.Unix()
59+
})
60+
61+
instanceAmi := *imagesRes.Images[0].ImageId
62+
63+
// key-pair
64+
svc.ImportKeyPair(&ec2.ImportKeyPairInput{
65+
KeyName: aws.String(pairName),
66+
PublicKeyMaterial: []byte(keyPublic),
67+
})
68+
//if err != nil {
69+
//return err
70+
//}
71+
72+
// securityGroup
73+
var vpcID, sgID string
74+
if len(securityGroup) == 0 {
75+
securityGroup = "cml"
76+
77+
vpcsDesc, _ := svc.DescribeVpcs(&ec2.DescribeVpcsInput{})
78+
vpcID = *vpcsDesc.Vpcs[0].VpcId
79+
80+
gpResult, err := svc.CreateSecurityGroup(&ec2.CreateSecurityGroupInput{
81+
GroupName: aws.String(securityGroup),
82+
Description: aws.String("CML security group"),
83+
VpcId: aws.String(vpcID),
84+
})
85+
86+
if err == nil {
87+
ipPermissions := []*ec2.IpPermission{
88+
(&ec2.IpPermission{}).
89+
SetIpProtocol("-1").
90+
SetFromPort(-1).
91+
SetToPort(-1).
92+
SetIpRanges([]*ec2.IpRange{
93+
{CidrIp: aws.String("0.0.0.0/0")},
94+
}),
95+
}
96+
97+
svc.AuthorizeSecurityGroupIngress(&ec2.AuthorizeSecurityGroupIngressInput{
98+
GroupId: aws.String(*gpResult.GroupId),
99+
IpPermissions: ipPermissions,
100+
})
101+
102+
svc.AuthorizeSecurityGroupEgress(&ec2.AuthorizeSecurityGroupEgressInput{
103+
GroupId: aws.String(*gpResult.GroupId),
104+
IpPermissions: ipPermissions,
105+
})
106+
}
107+
}
108+
109+
sgDesc, err := svc.DescribeSecurityGroupsWithContext(ctx, &ec2.DescribeSecurityGroupsInput{
110+
Filters: []*ec2.Filter{
111+
{
112+
Name: aws.String("group-name"),
113+
Values: []*string{aws.String(securityGroup)},
114+
},
115+
},
116+
})
117+
if err != nil {
118+
return err
119+
}
120+
121+
sgID = *sgDesc.SecurityGroups[0].GroupId
122+
vpcID = *sgDesc.SecurityGroups[0].VpcId
123+
124+
subDesc, _ := svc.DescribeSubnetsWithContext(ctx, &ec2.DescribeSubnetsInput{
125+
Filters: []*ec2.Filter{
126+
{
127+
Name: aws.String("vpc-id"),
128+
Values: []*string{aws.String(vpcID)},
129+
},
130+
},
131+
})
132+
133+
//launch instance
134+
runResult, err := svc.RunInstancesWithContext(ctx, &ec2.RunInstancesInput{
135+
UserData: aws.String(userData),
136+
ImageId: aws.String(instanceAmi),
137+
KeyName: aws.String(pairName),
138+
InstanceType: aws.String(instanceType),
139+
MinCount: aws.Int64(1),
140+
MaxCount: aws.Int64(1),
141+
SecurityGroupIds: []*string{aws.String(sgID)},
142+
SubnetId: aws.String(*subDesc.Subnets[0].SubnetId),
143+
BlockDeviceMappings: []*ec2.BlockDeviceMapping{
144+
{
145+
//VirtualName: aws.String("Root"),
146+
DeviceName: aws.String("/dev/sda1"),
147+
Ebs: &ec2.EbsBlockDevice{
148+
DeleteOnTermination: aws.Bool(true),
149+
Encrypted: aws.Bool(false),
150+
//Iops: aws.Int64(0),
151+
VolumeSize: aws.Int64(int64(hddSize)),
152+
VolumeType: aws.String("gp2"),
153+
},
154+
},
155+
},
156+
})
157+
if err != nil {
158+
return err
159+
}
160+
161+
instanceID := *runResult.Instances[0].InstanceId
162+
163+
// Add name to the created instance
164+
_, err = svc.CreateTags(&ec2.CreateTagsInput{
165+
Resources: []*string{aws.String(instanceID)},
166+
Tags: []*ec2.Tag{
167+
{
168+
Key: aws.String("Name"),
169+
Value: aws.String(instanceName),
170+
},
171+
{
172+
Key: aws.String("Id"),
173+
Value: aws.String(d.Id()),
174+
},
175+
},
176+
})
177+
if err != nil {
178+
return err
179+
}
180+
181+
statusInput := ec2.DescribeInstancesInput{
182+
InstanceIds: []*string{aws.String(instanceID)},
183+
Filters: []*ec2.Filter{
184+
{
185+
Name: aws.String("instance-state-name"),
186+
Values: []*string{aws.String("running")},
187+
},
188+
},
189+
}
190+
191+
svc.WaitUntilInstanceExistsWithContext(ctx, &statusInput)
192+
193+
descResult, err := svc.DescribeInstancesWithContext(ctx, &statusInput)
194+
if err != nil {
195+
return err
196+
}
197+
198+
instanceDesc := descResult.Reservations[0].Instances[0]
199+
d.Set("instance_ip", instanceDesc.PublicIpAddress)
200+
d.Set("instance_launch_time", instanceDesc.LaunchTime.Format(time.RFC3339))
201+
202+
return nil
203+
}
204+
205+
//ResourceMachineDelete deletes AWS instance
206+
func ResourceMachineDelete(ctx context.Context, d *schema.ResourceData, m interface{}) error {
207+
id := aws.String(d.Id())
208+
region := getRegion(d.Get("region").(string))
209+
210+
svc, err := awsClient(region)
211+
if err != nil {
212+
return err
213+
}
214+
215+
descResult, err := svc.DescribeInstancesWithContext(ctx, &ec2.DescribeInstancesInput{
216+
Filters: []*ec2.Filter{
217+
{
218+
Name: aws.String("tag:Id"),
219+
Values: []*string{id},
220+
},
221+
},
222+
})
223+
if err != nil {
224+
return err
225+
}
226+
227+
svc.DeleteKeyPair(&ec2.DeleteKeyPairInput{
228+
KeyName: id,
229+
})
230+
231+
instanceID := *descResult.Reservations[0].Instances[0].InstanceId
232+
_, err = svc.TerminateInstances(&ec2.TerminateInstancesInput{
233+
InstanceIds: []*string{
234+
aws.String(instanceID),
235+
},
236+
DryRun: aws.Bool(false),
237+
})
238+
if err != nil {
239+
return err
240+
}
241+
242+
return nil
243+
}
244+
245+
func awsClient(region string) (*ec2.EC2, error) {
246+
sess, err := session.NewSession(&aws.Config{
247+
Region: aws.String(region),
248+
//Credentials: credentials.NewStaticCredentials(conf.AWS_ACCESS_KEY_ID, conf.AWS_SECRET_ACCESS_KEY, ""),
249+
})
250+
251+
svc := ec2.New(sess)
252+
return svc, err
253+
}
254+
255+
func getRegion(region string) string {
256+
instanceRegions := make(map[string]string)
257+
instanceRegions["us-east"] = "us-east-1"
258+
instanceRegions["us-west"] = "us-west-1"
259+
instanceRegions["eu-north"] = "eu-north-1"
260+
instanceRegions["eu-west"] = "eu-west-1"
261+
if val, ok := instanceRegions[region]; ok {
262+
return val
263+
}
264+
265+
return region
266+
}
267+
268+
func getInstanceType(instanceType string, instanceGPU string) string {
269+
instanceTypes := make(map[string]string)
270+
instanceTypes["m"] = "m5.2xlarge"
271+
instanceTypes["l"] = "m5.8xlarge"
272+
instanceTypes["xl"] = "m5.16xlarge"
273+
instanceTypes["mk80"] = "p2.xlarge"
274+
instanceTypes["lk80"] = "p2.8xlarge"
275+
instanceTypes["xlk80"] = "p2.16xlarge"
276+
instanceTypes["mtesla"] = "p3.xlarge"
277+
instanceTypes["ltesla"] = "p3.8xlarge"
278+
instanceTypes["xltesla"] = "p3.16xlarge"
279+
280+
if val, ok := instanceTypes[instanceType+instanceGPU]; ok {
281+
return val
282+
}
283+
284+
return instanceType
285+
}

0 commit comments

Comments
 (0)