Skip to content

Commit 641e02c

Browse files
committed
feat: refactor mac request / release flow
This commit move the time consuming effort for having fresh machines on the mac pool from the request action to the release. Now release will manage the root volume replace task and request will create new user credentials and set machine as locked to avoid new workloads to make use of it Signed-off-by: Adrian Riobo <[email protected]>
1 parent 84db51d commit 641e02c

File tree

7 files changed

+81
-140
lines changed

7 files changed

+81
-140
lines changed

cmd/mapt/cmd/aws/hosts/mac.go

+2-10
Original file line numberDiff line numberDiff line change
@@ -23,10 +23,10 @@ const (
2323
dhIDDesc string = "id for the dedicated host"
2424
arch string = "arch"
2525
archDesc string = "mac architecture allowed values x86, m1, m2"
26-
archDefault string = "m2"
26+
archDefault string = mac.DefaultArch
2727
osVersion string = "version"
2828
osVersionDesc string = "macos operating system vestion 11, 12 on x86 and m1/m2; 13, 14 on all archs"
29-
osDefault string = "14"
29+
osDefault string = mac.DefaultOSVersion
3030
fixedLocation string = "fixed-location"
3131
fixedLocationDesc string = "if this flag is set the host will be created only on the region set by the AWS Env (AWS_DEFAULT_REGION)"
3232
)
@@ -96,14 +96,6 @@ func getMacRequest() *cobra.Command {
9696
flagSet.Bool(airgap, false, airgapDesc)
9797
flagSet.AddFlagSet(params.GetGHActionsFlagset())
9898
c.PersistentFlags().AddFlagSet(flagSet)
99-
err := c.MarkPersistentFlagRequired(arch)
100-
if err != nil {
101-
logging.Error(err)
102-
}
103-
err = c.MarkPersistentFlagRequired(osVersion)
104-
if err != nil {
105-
logging.Error(err)
106-
}
10799
return c
108100
}
109101

docs/aws/mac.drawio

+13-74
Large diffs are not rendered by default.

docs/aws/mac.svg

+1-1
Loading

pkg/provider/aws/action/mac/constants.go

+3-2
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ const (
77
awsMacMachineID = "amm"
88

99
customResourceTypeLock = "rh:qe:aws:mac:lock"
10+
customResourceTypeKey = "rh:mapt:aws:mac:key"
1011

1112
outputLock = "ammLock"
1213
outputHost = "ammHost"
@@ -19,8 +20,8 @@ const (
1920
outputRegion = "ammRegion"
2021

2122
amiRegex = "amzn-ec2-macos-%s*"
22-
archDefault = "m2"
23-
osVersionDefault = "14"
23+
DefaultArch = "m2"
24+
DefaultOSVersion = "15"
2425

2526
vncDefaultPort int = 5900
2627
diskSize int = 100

pkg/provider/aws/action/mac/mac-machine.go

+17-30
Original file line numberDiff line numberDiff line change
@@ -83,38 +83,25 @@ func (r *MacRequest) replaceMachine(h *HostInformation) error {
8383
return err
8484
}
8585
logging.Debugf("Replacing root volume for AMI %s", *ami.Image.ImageId)
86-
_, err = qEC2.ReplaceRootVolume(
86+
if _, err = qEC2.ReplaceRootVolume(
8787
qEC2.ReplaceRootVolumeRequest{
8888
Region: *h.Region,
8989
InstanceID: *h.Host.Instances[0].InstanceId,
9090
// Needto lookup for AMI + check if copy is required
9191
AMIID: *ami.Image.ImageId,
92-
})
93-
if err != nil {
94-
return err
95-
}
96-
r.lock = true
97-
if err := r.manageMacMachine(h); err != nil {
92+
Wait: true,
93+
}); err != nil {
9894
return err
9995
}
100-
// replace will run again the boostrap script to generate
101-
// and set new keys to access the machine
102-
r.replace = true
96+
r.lock = false
10397
return r.manageMacMachine(h)
10498
}
10599

106-
// Release will set the lock as false
107-
func (r *MacRequest) releaseLock(h *HostInformation) error {
108-
r.lock = false
109-
lockURN := fmt.Sprintf("urn:pulumi:%s::%s::%s::%s",
110-
maptContext.StackNameByProject(stackMacMachine),
111-
maptContext.ProjectName(),
112-
customResourceTypeLock,
113-
resourcesUtil.GetResourceName(
114-
r.Prefix, awsMacMachineID, "mac-lock"))
115-
116-
// rh:qe:aws:mac:lock main-amm-mac-lock
117-
return r.manageMacMachineTargets(h, []string{lockURN})
100+
// Run the bootstrap script creating new access credentials for the user
101+
func (r *MacRequest) replaceUserAccess(h *HostInformation) error {
102+
r.replace = true
103+
r.lock = true
104+
return r.manageMacMachine(h)
118105
}
119106

120107
// Release will set the lock as false
@@ -236,14 +223,15 @@ func (r *MacRequest) deployerMachine(ctx *pulumi.Context) error {
236223
ctx.Export(fmt.Sprintf("%s-%s", r.Prefix, outputUserPassword), userPassword.Result)
237224
ctx.Export(fmt.Sprintf("%s-%s", r.Prefix, outputUserPrivateKey),
238225
ukp.PrivateKey.PrivateKeyPem)
239-
// Create a lock on the machine
240-
if err := machineLock(ctx,
241-
resourcesUtil.GetResourceName(
242-
r.Prefix, awsMacMachineID, "mac-lock"), r.lock); err != nil {
226+
readiness, err := r.readiness(ctx, i, ukp.PrivateKey, bastion, []pulumi.Resource{bc})
227+
if err != nil {
243228
return err
244229
}
245230
ctx.Export(fmt.Sprintf("%s-%s", r.Prefix, outputLock), pulumi.Bool(r.lock))
246-
return r.readiness(ctx, i, ukp.PrivateKey, bastion, []pulumi.Resource{bc})
231+
return machineLock(ctx,
232+
resourcesUtil.GetResourceName(
233+
r.Prefix, awsMacMachineID, "mac-lock"), r.lock,
234+
pulumi.DependsOn([]pulumi.Resource{readiness}))
247235
}
248236

249237
// Write exported values in context to files o a selected target folder
@@ -400,8 +388,8 @@ func (r *MacRequest) readiness(ctx *pulumi.Context,
400388
m *ec2.Instance,
401389
mk *tls.PrivateKey,
402390
b *bastion.Bastion,
403-
dependecies []pulumi.Resource) error {
404-
_, err := remote.NewCommand(ctx,
391+
dependecies []pulumi.Resource) (*remote.Command, error) {
392+
return remote.NewCommand(ctx,
405393
resourcesUtil.GetResourceName(r.Prefix, awsMacMachineID, "readiness-cmd"),
406394
&remote.CommandArgs{
407395
Connection: remoteCommandArgs(m, mk, b),
@@ -412,7 +400,6 @@ func (r *MacRequest) readiness(ctx *pulumi.Context,
412400
Create: remoteTimeout,
413401
Update: remoteTimeout}),
414402
pulumi.DependsOn(dependecies))
415-
return err
416403
}
417404

418405
// helper function to set the connection args

pkg/provider/aws/action/mac/mac.go

+15-19
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,9 @@ import (
1010
"github.com/redhat-developer/mapt/pkg/provider/aws/data"
1111
"github.com/redhat-developer/mapt/pkg/provider/aws/services/tag"
1212
"github.com/redhat-developer/mapt/pkg/util/logging"
13-
14-
ec2Types "github.com/aws/aws-sdk-go-v2/service/ec2/types"
1513
)
1614

17-
// Request could be interpreted as a general way to create / release
15+
// Request could be interpreted as a general way to create / get a machine
1816
//
1917
// Some project will request a mac machine
2018
// based on tags it will check if there is any existing mac machine (based on labels + arch + MaxPoolSize)
@@ -50,7 +48,7 @@ func Request(r *MacRequest) error {
5048
}
5149
return create(r, hi)
5250
}
53-
err = r.replaceMachine(hi)
51+
err = r.replaceUserAccess(hi)
5452
if err != nil {
5553
return err
5654
}
@@ -78,13 +76,14 @@ func Release(prefix string, hostID string) error {
7876
maptContext.InitBase(
7977
*hi.ProjectName,
8078
*hi.BackedURL)
79+
8180
// Set a default request
8281
r := &MacRequest{
8382
Prefix: prefix,
84-
Architecture: archDefault,
85-
Version: osVersionDefault,
83+
Architecture: DefaultArch,
84+
Version: DefaultOSVersion,
8685
}
87-
return r.releaseLock(hi)
86+
return r.replaceMachine(hi)
8887
}
8988

9089
// Initial scenario consider 1 machine
@@ -100,28 +99,25 @@ func Destroy(prefix, hostID string) error {
10099
maptContext.InitBase(
101100
*hi.ProjectName,
102101
*hi.BackedURL)
103-
// Check if dh is available and it has no instance on it
104-
// otherwise we can not release it
105-
if hi.Host.State == ec2Types.AllocationStateAvailable &&
106-
len(host.Instances) == 0 {
107-
return aws.DestroyStack(aws.DestroyStackRequest{
108-
Stackname: stackDedicatedHost,
109-
// TODO check if needed to add region for backedURL
110-
Region: *hi.Region,
111-
BackedURL: *hi.BackedURL,
112-
})
113-
}
114102
// Dedicated host is not on a valid state to be deleted
115103
// With same backedURL check if machine is locked
116104
machineLocked, err := isMachineLocked(prefix, hi)
117105
if err != nil {
118106
return err
119107
}
120108
if !machineLocked {
121-
return aws.DestroyStack(aws.DestroyStackRequest{
109+
if err := aws.DestroyStack(aws.DestroyStackRequest{
122110
Stackname: stackMacMachine,
123111
Region: *hi.Region,
124112
BackedURL: *hi.BackedURL,
113+
}); err != nil {
114+
return err
115+
}
116+
return aws.DestroyStack(aws.DestroyStackRequest{
117+
Stackname: stackDedicatedHost,
118+
// TODO check if needed to add region for backedURL
119+
Region: *hi.Region,
120+
BackedURL: *hi.BackedURL,
125121
})
126122
}
127123
logging.Debug("nothing to be destroyed")

pkg/provider/aws/services/ec2/compute/compute.go

+30-4
Original file line numberDiff line numberDiff line change
@@ -2,33 +2,59 @@ package compute
22

33
import (
44
"context"
5+
"fmt"
56

67
"github.com/aws/aws-sdk-go-v2/config"
78
"github.com/aws/aws-sdk-go-v2/service/ec2"
9+
"github.com/aws/aws-sdk-go-v2/service/ec2/types"
810
)
911

1012
type ReplaceRootVolumeRequest struct {
1113
Region string
1214
InstanceID string
1315
AMIID string
16+
Wait bool
1417
}
1518

1619
// This function will replace the root volume for a running ec2 instance
1720
// and will delete the replaced volume
18-
func ReplaceRootVolume(r ReplaceRootVolumeRequest) (*ec2.CreateReplaceRootVolumeTaskOutput, error) {
21+
// If wait flag is true on request the funcion will wait until the replace task succeed
22+
// otherwise it will trigger the task and return the id to reference it
23+
func ReplaceRootVolume(r ReplaceRootVolumeRequest) (*string, error) {
24+
ctx := context.Background()
1925
cfg, err := config.LoadDefaultConfig(
20-
context.Background(),
26+
ctx,
2127
config.WithRegion(r.Region))
2228
if err != nil {
2329
return nil, err
2430
}
2531
client := ec2.NewFromConfig(cfg)
2632
deleteReplacedRootVolume := true
27-
return client.CreateReplaceRootVolumeTask(
28-
context.Background(),
33+
// rrvt, err :=
34+
rrvt, err := client.CreateReplaceRootVolumeTask(
35+
ctx,
2936
&ec2.CreateReplaceRootVolumeTaskInput{
3037
InstanceId: &r.InstanceID,
3138
DeleteReplacedRootVolume: &deleteReplacedRootVolume,
3239
ImageId: &r.AMIID,
3340
})
41+
if err != nil {
42+
return rrvt.ReplaceRootVolumeTask.ReplaceRootVolumeTaskId, err
43+
}
44+
taskState := rrvt.ReplaceRootVolumeTask.TaskState
45+
for r.Wait && taskState != types.ReplaceRootVolumeTaskStateSucceeded {
46+
drvt, err := client.DescribeReplaceRootVolumeTasks(ctx, &ec2.DescribeReplaceRootVolumeTasksInput{
47+
ReplaceRootVolumeTaskIds: []string{*rrvt.ReplaceRootVolumeTask.ReplaceRootVolumeTaskId},
48+
})
49+
if err != nil {
50+
return rrvt.ReplaceRootVolumeTask.ReplaceRootVolumeTaskId, nil
51+
}
52+
if len(drvt.ReplaceRootVolumeTasks) == 0 {
53+
return rrvt.ReplaceRootVolumeTask.ReplaceRootVolumeTaskId,
54+
fmt.Errorf("something wrong happened checkding the replace root volume task with id %s",
55+
*rrvt.ReplaceRootVolumeTask.ReplaceRootVolumeTaskId)
56+
}
57+
taskState = drvt.ReplaceRootVolumeTasks[0].TaskState
58+
}
59+
return rrvt.ReplaceRootVolumeTask.ReplaceRootVolumeTaskId, nil
3460
}

0 commit comments

Comments
 (0)