Skip to content

Commit 8ab3cd7

Browse files
dacbdcasperdcl
andauthored
task implement "instance permission set" (#550)
Co-authored-by: Casper da Costa-Luis <casper.dcl@physics.org>
1 parent 5f3f581 commit 8ab3cd7

15 files changed

+320
-46
lines changed

docs/resources/task.md

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ resource "iterative_task" "example" {
5959
- `disk_size` - (Optional) Size of the ephemeral machine storage in GB. `-1`: automatic based on `image`.
6060
- `spot` - (Optional) Spot instance price. `-1`: disabled, `0`: automatic price, any other positive number: maximum bidding price in USD per hour (above which the instance is terminated until the price drops).
6161
- `image` - (Optional) [Machine image](#machine-image) to run the task with.
62+
- `permission_set` - (Optional) See [Permission Set](#permission-set) below.
6263
- `parallelism` - (Optional) Number of machines to be launched in parallel.
6364
- `storage.workdir` - (Optional) Local working directory to upload and use as the `script` working directory.
6465
- `storage.output` - (Optional) Results directory (**relative to `workdir`**) to download (default: no download).
@@ -257,6 +258,28 @@ In addition to generic regions, it's possible to specify any cloud region suppor
257258

258259
The `region` attribute is ignored.
259260

261+
## Permission Set
262+
263+
A set of "permissions" assigned to the `task` instance, format depends on the cloud provider
264+
265+
#### Amazon Web Services
266+
267+
An [instance profile `arn`](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/iam-roles-for-amazon-ec2.html), e.g.:
268+
`permission_set = "arn:aws:iam:1234567890:instance-profile/rolename"`
269+
270+
#### Google Cloud Platform
271+
272+
A service account email and a [list of scopes](https://cloud.google.com/sdk/gcloud/reference/alpha/compute/instances/set-scopes#--scopes), e.g.:
273+
`permission_set = "sa-name@project_id.iam.gserviceaccount.com,scopes=storage-rw"`
274+
275+
#### Microsoft Azure
276+
277+
[Not yet implemented](https://github.com/iterative/terraform-provider-iterative/issues/559)
278+
279+
#### Kubernetes
280+
281+
[Not yet implemented](https://github.com/iterative/terraform-provider-iterative/issues/560)
282+
260283
## Known Issues
261284

262285
### Kubernetes

iterative/resource_task.go

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,12 @@ func resourceTask() *schema.Resource {
5555
Optional: true,
5656
Default: "m",
5757
},
58+
"permission_set": {
59+
Type: schema.TypeString,
60+
ForceNew: true,
61+
Optional: true,
62+
Default: "",
63+
},
5864
"disk_size": {
5965
Type: schema.TypeInt,
6066
ForceNew: true,
@@ -332,8 +338,9 @@ func resourceTaskBuild(ctx context.Context, d *schema.ResourceData, m interface{
332338
},
333339
// Egress is open on every port
334340
},
335-
Spot: common.Spot(d.Get("spot").(float64)),
336-
Parallelism: uint16(d.Get("parallelism").(int)),
341+
Spot: common.Spot(d.Get("spot").(float64)),
342+
Parallelism: uint16(d.Get("parallelism").(int)),
343+
PermissionSet: d.Get("permission_set").(string),
337344
}
338345

339346
name := d.Id()
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
package resources
2+
3+
import (
4+
"context"
5+
"fmt"
6+
"regexp"
7+
8+
"github.com/aws/aws-sdk-go-v2/aws"
9+
"github.com/aws/aws-sdk-go-v2/service/ec2/types"
10+
11+
"terraform-provider-iterative/task/aws/client"
12+
)
13+
14+
func NewPermissionSet(client *client.Client, identifier string) *PermissionSet {
15+
ps := new(PermissionSet)
16+
ps.Client = client
17+
ps.Identifier = identifier
18+
return ps
19+
}
20+
21+
type PermissionSet struct {
22+
Client *client.Client
23+
Identifier string
24+
Resource *types.LaunchTemplateIamInstanceProfileSpecificationRequest
25+
}
26+
27+
func (ps *PermissionSet) Read(ctx context.Context) error {
28+
arn := ps.Identifier
29+
// "", "arn:*"
30+
if arn == "" {
31+
ps.Resource = nil
32+
return nil
33+
}
34+
re := regexp.MustCompile(`arn:aws:iam::[\d]*:instance-profile/[\S]*`)
35+
if re.MatchString(arn) {
36+
ps.Resource = &types.LaunchTemplateIamInstanceProfileSpecificationRequest{
37+
Arn: aws.String(arn),
38+
}
39+
return nil
40+
}
41+
return fmt.Errorf("invlaid IAM Instance Profile: %s", arn)
42+
}

task/aws/resources/resource_launch_template.go

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ import (
1616
"terraform-provider-iterative/task/common/machine"
1717
)
1818

19-
func NewLaunchTemplate(client *client.Client, identifier common.Identifier, securityGroup *SecurityGroup, image *Image, keyPair *KeyPair, credentials *Credentials, task common.Task) *LaunchTemplate {
19+
func NewLaunchTemplate(client *client.Client, identifier common.Identifier, securityGroup *SecurityGroup, permissionSet *PermissionSet, image *Image, keyPair *KeyPair, credentials *Credentials, task common.Task) *LaunchTemplate {
2020
l := new(LaunchTemplate)
2121
l.Client = client
2222
l.Identifier = identifier.Long()
@@ -25,6 +25,7 @@ func NewLaunchTemplate(client *client.Client, identifier common.Identifier, secu
2525
l.Dependencies.Image = image
2626
l.Dependencies.KeyPair = keyPair
2727
l.Dependencies.Credentials = credentials
28+
l.Dependencies.PermissionSet = permissionSet
2829
return l
2930
}
3031

@@ -37,6 +38,7 @@ type LaunchTemplate struct {
3738
*SecurityGroup
3839
*Image
3940
*Credentials
41+
*PermissionSet
4042
}
4143
Resource *types.LaunchTemplate
4244
}
@@ -71,11 +73,12 @@ func (l *LaunchTemplate) Create(ctx context.Context) error {
7173
input := ec2.CreateLaunchTemplateInput{
7274
LaunchTemplateName: aws.String(l.Identifier),
7375
LaunchTemplateData: &types.RequestLaunchTemplateData{
74-
UserData: aws.String(userData),
75-
ImageId: l.Dependencies.Image.Resource.ImageId,
76-
KeyName: l.Dependencies.KeyPair.Resource.KeyName,
77-
InstanceType: types.InstanceType(size),
78-
SecurityGroupIds: []string{aws.ToString(l.Dependencies.SecurityGroup.Resource.GroupId)},
76+
UserData: aws.String(userData),
77+
ImageId: l.Dependencies.Image.Resource.ImageId,
78+
KeyName: l.Dependencies.KeyPair.Resource.KeyName,
79+
InstanceType: types.InstanceType(size),
80+
SecurityGroupIds: []string{aws.ToString(l.Dependencies.SecurityGroup.Resource.GroupId)},
81+
IamInstanceProfile: l.Dependencies.PermissionSet.Resource,
7982
BlockDeviceMappings: []types.LaunchTemplateBlockDeviceMappingRequest{
8083
{
8184
DeviceName: aws.String("/dev/sda1"),

task/aws/task.go

Lines changed: 21 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,10 @@ func New(ctx context.Context, cloud common.Cloud, identifier common.Identifier,
3434
t.Client,
3535
t.Attributes.Environment.Image,
3636
)
37+
t.DataSources.PermissionSet = resources.NewPermissionSet(
38+
t.Client,
39+
t.Attributes.PermissionSet,
40+
)
3741
t.Resources.Bucket = resources.NewBucket(
3842
t.Client,
3943
t.Identifier,
@@ -57,6 +61,7 @@ func New(ctx context.Context, cloud common.Cloud, identifier common.Identifier,
5761
t.Client,
5862
t.Identifier,
5963
t.Resources.SecurityGroup,
64+
t.DataSources.PermissionSet,
6065
t.DataSources.Image,
6166
t.Resources.KeyPair,
6267
t.DataSources.Credentials,
@@ -82,6 +87,7 @@ type Task struct {
8287
*resources.DefaultVPCSubnet
8388
*resources.Image
8489
*resources.Credentials
90+
*resources.PermissionSet
8591
}
8692
Resources struct {
8793
*resources.Bucket
@@ -94,49 +100,53 @@ type Task struct {
94100

95101
func (t *Task) Create(ctx context.Context) error {
96102
logrus.Info("Creating resources...")
97-
logrus.Info("[1/11] Importing DefaultVPC...")
103+
logrus.Info("[1/12] Parsing PermissionSet...")
104+
if err := t.DataSources.PermissionSet.Read(ctx); err != nil {
105+
return err
106+
}
107+
logrus.Info("[2/12] Importing DefaultVPC...")
98108
if err := t.DataSources.DefaultVPC.Read(ctx); err != nil {
99109
return err
100110
}
101-
logrus.Info("[2/11] Importing DefaultVPCSubnet...")
111+
logrus.Info("[3/12] Importing DefaultVPCSubnet...")
102112
if err := t.DataSources.DefaultVPCSubnet.Read(ctx); err != nil {
103113
return err
104114
}
105-
logrus.Info("[3/11] Reading Image...")
115+
logrus.Info("[4/12] Reading Image...")
106116
if err := t.DataSources.Image.Read(ctx); err != nil {
107117
return err
108118
}
109-
logrus.Info("[4/11] Creating Bucket...")
119+
logrus.Info("[5/12] Creating Bucket...")
110120
if err := t.Resources.Bucket.Create(ctx); err != nil {
111121
return err
112122
}
113-
logrus.Info("[5/11] Creating SecurityGroup...")
123+
logrus.Info("[6/12] Creating SecurityGroup...")
114124
if err := t.Resources.SecurityGroup.Create(ctx); err != nil {
115125
return err
116126
}
117-
logrus.Info("[6/11] Creating KeyPair...")
127+
logrus.Info("[7/12] Creating KeyPair...")
118128
if err := t.Resources.KeyPair.Create(ctx); err != nil {
119129
return err
120130
}
121-
logrus.Info("[7/11] Reading Credentials...")
131+
logrus.Info("[8/12] Reading Credentials...")
122132
if err := t.DataSources.Credentials.Read(ctx); err != nil {
123133
return err
124134
}
125-
logrus.Info("[8/11] Creating LaunchTemplate...")
135+
logrus.Info("[9/12] Creating LaunchTemplate...")
126136
if err := t.Resources.LaunchTemplate.Create(ctx); err != nil {
127137
return err
128138
}
129-
logrus.Info("[9/11] Creating AutoScalingGroup...")
139+
logrus.Info("[10/12] Creating AutoScalingGroup...")
130140
if err := t.Resources.AutoScalingGroup.Create(ctx); err != nil {
131141
return err
132142
}
133-
logrus.Info("[10/11] Uploading Directory...")
143+
logrus.Info("[11/12] Uploading Directory...")
134144
if t.Attributes.Environment.Directory != "" {
135145
if err := t.Push(ctx, t.Attributes.Environment.Directory); err != nil {
136146
return err
137147
}
138148
}
139-
logrus.Info("[11/11] Starting task...")
149+
logrus.Info("[12/12] Starting task...")
140150
if err := t.Start(ctx); err != nil {
141151
return err
142152
}
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
package resources
2+
3+
import (
4+
"context"
5+
"fmt"
6+
7+
"github.com/Azure/azure-sdk-for-go/services/compute/mgmt/2020-06-30/compute"
8+
9+
"terraform-provider-iterative/task/az/client"
10+
)
11+
12+
func NewPermissionSet(client *client.Client, identifer string) *PermissionSet {
13+
ps := new(PermissionSet)
14+
ps.Client = client
15+
ps.Identifier = identifer
16+
return ps
17+
}
18+
19+
type PermissionSet struct {
20+
Client *client.Client
21+
Identifier string
22+
Resource *compute.VirtualMachineScaleSetIdentity
23+
}
24+
25+
func (ps *PermissionSet) Read(ctx context.Context) error {
26+
if ps.Identifier != "" {
27+
return fmt.Errorf("not yet implemented")
28+
}
29+
ps.Resource = nil
30+
return nil
31+
}

task/az/resources/resource_virtual_machine_scale_set.go

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ import (
2121
"terraform-provider-iterative/task/common/machine"
2222
)
2323

24-
func NewVirtualMachineScaleSet(client *client.Client, identifier common.Identifier, resourceGroup *ResourceGroup, subnet *Subnet, securityGroup *SecurityGroup, credentials *Credentials, task *common.Task) *VirtualMachineScaleSet {
24+
func NewVirtualMachineScaleSet(client *client.Client, identifier common.Identifier, resourceGroup *ResourceGroup, subnet *Subnet, securityGroup *SecurityGroup, permissionSet *PermissionSet, credentials *Credentials, task *common.Task) *VirtualMachineScaleSet {
2525
v := new(VirtualMachineScaleSet)
2626
v.Client = client
2727
v.Identifier = identifier.Long()
@@ -35,6 +35,7 @@ func NewVirtualMachineScaleSet(client *client.Client, identifier common.Identifi
3535
v.Dependencies.Subnet = subnet
3636
v.Dependencies.SecurityGroup = securityGroup
3737
v.Dependencies.Credentials = credentials
38+
v.Dependencies.PermissionSet = permissionSet
3839
return v
3940
}
4041

@@ -57,6 +58,7 @@ type VirtualMachineScaleSet struct {
5758
*Subnet
5859
*SecurityGroup
5960
*Credentials
61+
*PermissionSet
6062
}
6163
Resource *compute.VirtualMachineScaleSet
6264
}
@@ -126,6 +128,7 @@ func (v *VirtualMachineScaleSet) Create(ctx context.Context) error {
126128
Tier: to.StringPtr("Standard"),
127129
Capacity: to.Int64Ptr(0),
128130
},
131+
Identity: v.Dependencies.PermissionSet.Resource,
129132
VirtualMachineScaleSetProperties: &compute.VirtualMachineScaleSetProperties{
130133
UpgradePolicy: &compute.UpgradePolicy{
131134
Mode: compute.UpgradeModeManual,

task/az/task.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,10 @@ func New(ctx context.Context, cloud common.Cloud, identifier common.Identifier,
2323
t.Client = client
2424
t.Identifier = identifier
2525
t.Attributes = task
26+
t.DataSources.PermissionSet = resources.NewPermissionSet(
27+
t.Client,
28+
t.Attributes.PermissionSet,
29+
)
2630
t.Resources.ResourceGroup = resources.NewResourceGroup(
2731
t.Client,
2832
t.Identifier,
@@ -69,6 +73,7 @@ func New(ctx context.Context, cloud common.Cloud, identifier common.Identifier,
6973
t.Resources.ResourceGroup,
7074
t.Resources.Subnet,
7175
t.Resources.SecurityGroup,
76+
t.DataSources.PermissionSet,
7277
t.DataSources.Credentials,
7378
&t.Attributes,
7479
)
@@ -81,6 +86,7 @@ type Task struct {
8186
Attributes common.Task
8287
DataSources struct {
8388
*resources.Credentials
89+
*resources.PermissionSet
8490
}
8591
Resources struct {
8692
*resources.ResourceGroup

task/common/values.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ type Task struct {
4747
Size
4848
Environment
4949
Firewall
50+
PermissionSet string
5051
Spot
5152
Parallelism uint16
5253
Tags map[string]string // Deprecated

0 commit comments

Comments
 (0)