Skip to content

Commit 94e78a9

Browse files
committed
chore: aws mac pool allow orchestrate serverless stack, to allow several task specs
Signed-off-by: Adrian Riobo <[email protected]>
1 parent 427bf26 commit 94e78a9

39 files changed

+1639
-1077
lines changed

Makefile

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@ VERSION ?= 0.9.0-dev
22
CONTAINER_MANAGER ?= podman
33

44
# Image URL to use all building/pushing image targets
5-
IMG ?= quay.io/redhat-developer/mapt:v${VERSION}
6-
TKN_IMG ?= quay.io/redhat-developer/mapt:v${VERSION}-tkn
5+
IMG ?= ghcr.io/redhat-developer/mapt:pr-421
6+
TKN_IMG ?= ghcr.io/redhat-developer/mapt:pr-421-tkn
77

88
# Integrations
99
# renovate: datasource=github-releases depName=cirruslabs/cirrus-cli

cmd/mapt/cmd/aws/services/mac-pool.go

Lines changed: 65 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ const (
2020
cmdHousekeep = "house-keep"
2121
cmdHousekeepDesc = "house keeping for mac pool. Detroy old machines on over capacity and create new ones if capacity not meet"
2222

23+
// Pool params
2324
paramName = "name"
2425
paramNameDesc = "pool name it is a unique identifier for the pool. The name should be unique for the whole AWS account"
2526
paramOfferedCapacity = "offered-capacity"
@@ -28,6 +29,23 @@ const (
2829
paramMaxSize = "max-size"
2930
paramMaxSizeDesc = "max number of machines in the pool"
3031
paramMaxSizeDefault = 2
32+
// Machines in the pool params
33+
paramVPCID = "vpcid"
34+
paramVPCIDDesc = "VPC Id to setup mac machines"
35+
paramVPCIDDefault = ""
36+
paramAZID = "azid"
37+
paramAZIDDesc = "AZ Id to setup mac machines"
38+
paramAZIDDefault = ""
39+
paramSubnetID = "subnetid"
40+
paramSubnetIDDesc = "Subnet Id to setup mac machines"
41+
paramSubnetIDDefault = ""
42+
paramSSHSGID = "ssh-sgid"
43+
paramSSHSGIDDesc = "Security group Id to securize ssh access to machines. SSH can only be used from instances with this SG."
44+
paramSSHSGIDDefault = ""
45+
// Request / Release
46+
paramTicket = "ticket"
47+
paramTicketDesc = "this is a unique identifier to tag the dedicated host meanwhile it is being locked to identify the request which locked it. It will be used on release to identify the machine being released"
48+
paramTicketDefault = ""
3149
)
3250

3351
func GetMacPoolCmd() *cobra.Command {
@@ -67,14 +85,13 @@ func create() *cobra.Command {
6785
DebugLevel: viper.GetUint(params.DebugLevel),
6886
Tags: viper.GetStringMapString(params.Tags),
6987
},
70-
&macpool.MacPoolRequestArgs{
88+
&macpool.PoolRequestArgs{
7189
Prefix: "main",
72-
PoolName: viper.GetString(paramName),
90+
Name: viper.GetString(paramName),
7391
Architecture: viper.GetString(awsParams.MACArch),
7492
OSVersion: viper.GetString(awsParams.MACOSVersion),
7593
OfferedCapacity: viper.GetInt(paramOfferedCapacity),
76-
MaxSize: viper.GetInt(paramMaxSize),
77-
FixedLocation: viper.IsSet(awsParams.MACFixedLocation)}); err != nil {
94+
MaxSize: viper.GetInt(paramMaxSize)}); err != nil {
7895
logging.Error(err)
7996
}
8097
return nil
@@ -89,7 +106,6 @@ func create() *cobra.Command {
89106
flagSet.StringP(awsParams.MACArch, "", awsParams.MACArchDefault, awsParams.MACArchDesc)
90107
flagSet.StringP(awsParams.MACOSVersion, "", awsParams.MACOSVersionDefault, awsParams.MACOSVersionDesc)
91108
flagSet.StringToStringP(params.Tags, "", nil, params.TagsDesc)
92-
flagSet.Bool(awsParams.MACFixedLocation, false, awsParams.MACFixedLocationDesc)
93109
c.PersistentFlags().AddFlagSet(flagSet)
94110
return c
95111
}
@@ -138,14 +154,21 @@ func houseKeep() *cobra.Command {
138154
DebugLevel: viper.GetUint(params.DebugLevel),
139155
Tags: viper.GetStringMapString(params.Tags),
140156
},
141-
&macpool.MacPoolRequestArgs{
142-
Prefix: "main",
143-
PoolName: viper.GetString(paramName),
144-
Architecture: viper.GetString(awsParams.MACArch),
145-
OSVersion: viper.GetString(awsParams.MACOSVersion),
146-
OfferedCapacity: viper.GetInt(paramOfferedCapacity),
147-
MaxSize: viper.GetInt(paramMaxSize),
148-
FixedLocation: viper.IsSet(awsParams.MACFixedLocation)}); err != nil {
157+
&macpool.HouseKeepRequestArgs{
158+
Pool: &macpool.PoolRequestArgs{
159+
Prefix: "main",
160+
Name: viper.GetString(paramName),
161+
Architecture: viper.GetString(awsParams.MACArch),
162+
OSVersion: viper.GetString(awsParams.MACOSVersion),
163+
OfferedCapacity: viper.GetInt(paramOfferedCapacity),
164+
MaxSize: viper.GetInt(paramMaxSize),
165+
},
166+
Machine: &macpool.MachineRequestArgs{
167+
VPCID: viper.GetString(paramVPCID),
168+
AZID: viper.GetString(paramAZID),
169+
SubnetID: viper.GetString(paramSubnetID),
170+
SSHSGID: viper.GetString(paramSSHSGID)},
171+
}); err != nil {
149172
logging.Error(err)
150173
}
151174
return nil
@@ -158,8 +181,11 @@ func houseKeep() *cobra.Command {
158181
flagSet.Int(paramMaxSize, paramMaxSizeDefault, paramMaxSizeDesc)
159182
flagSet.StringP(awsParams.MACArch, "", awsParams.MACArchDefault, awsParams.MACArchDesc)
160183
flagSet.StringP(awsParams.MACOSVersion, "", awsParams.MACOSVersion, awsParams.MACOSVersionDefault)
161-
flagSet.Bool(awsParams.MACFixedLocation, false, awsParams.MACFixedLocationDesc)
162184
flagSet.Bool(params.Serverless, false, params.ServerlessDesc)
185+
flagSet.StringP(paramVPCID, "", paramVPCIDDefault, paramVPCIDDesc)
186+
flagSet.StringP(paramAZID, "", paramAZIDDefault, paramAZIDDesc)
187+
flagSet.StringP(paramSubnetID, "", paramSubnetIDDefault, paramSubnetIDDesc)
188+
flagSet.StringP(paramSSHSGID, "", paramSSHSGIDDefault, paramSSHSGIDDesc)
163189
c.PersistentFlags().AddFlagSet(flagSet)
164190
return c
165191
}
@@ -209,7 +235,14 @@ func request() *cobra.Command {
209235
PoolName: viper.GetString(paramName),
210236
Architecture: viper.GetString(awsParams.MACArch),
211237
OSVersion: viper.GetString(awsParams.MACOSVersion),
212-
Timeout: viper.GetString(params.Timeout),
238+
Machine: &macpool.MachineRequestArgs{
239+
VPCID: viper.GetString(paramVPCID),
240+
AZID: viper.GetString(paramAZID),
241+
SubnetID: viper.GetString(paramSubnetID),
242+
SSHSGID: viper.GetString(paramSSHSGID),
243+
},
244+
Ticket: viper.GetString(paramTicket),
245+
Timeout: viper.GetString(params.Timeout),
213246
}); err != nil {
214247
logging.Error(err)
215248
}
@@ -223,6 +256,11 @@ func request() *cobra.Command {
223256
flagSet.StringP(awsParams.MACArch, "", awsParams.MACArchDefault, awsParams.MACArchDesc)
224257
flagSet.StringP(awsParams.MACOSVersion, "", awsParams.MACOSVersion, awsParams.MACOSVersionDefault)
225258
flagSet.StringP(params.Timeout, "", "", params.TimeoutDesc)
259+
flagSet.StringP(paramVPCID, "", paramVPCIDDefault, paramVPCIDDesc)
260+
flagSet.StringP(paramAZID, "", paramAZIDDefault, paramAZIDDesc)
261+
flagSet.StringP(paramSubnetID, "", paramSubnetIDDefault, paramSubnetIDDesc)
262+
flagSet.StringP(paramSSHSGID, "", paramSSHSGIDDefault, paramSSHSGIDDesc)
263+
flagSet.StringP(paramTicket, "", paramTicketDefault, paramTicketDesc)
226264
flagSet.Bool(params.Serverless, false, params.ServerlessDesc)
227265
flagSet.Bool(params.Remote, false, params.RemoteDesc)
228266
flagSet.AddFlagSet(params.GetGHActionsFlagset())
@@ -247,20 +285,26 @@ func release() *cobra.Command {
247285
Serverless: viper.IsSet(params.Serverless),
248286
Remote: viper.IsSet(params.Remote),
249287
},
250-
viper.GetString(awsParams.MACDHID)); err != nil {
288+
&macpool.MachineRequestArgs{
289+
VPCID: viper.GetString(paramVPCID),
290+
AZID: viper.GetString(paramAZID),
291+
SubnetID: viper.GetString(paramSubnetID),
292+
SSHSGID: viper.GetString(paramSSHSGID),
293+
},
294+
viper.GetString(paramTicket)); err != nil {
251295
logging.Error(err)
252296
}
253297
return nil
254298
},
255299
}
256300
flagSet := pflag.NewFlagSet(awsParams.MACReleaseCmd, pflag.ExitOnError)
257-
flagSet.StringP(awsParams.MACDHID, "", "", awsParams.MACDHIDDesc)
301+
flagSet.StringP(paramVPCID, "", paramVPCIDDefault, paramVPCIDDesc)
302+
flagSet.StringP(paramAZID, "", paramAZIDDefault, paramAZIDDesc)
303+
flagSet.StringP(paramSubnetID, "", paramSubnetIDDefault, paramSubnetIDDesc)
304+
flagSet.StringP(paramSSHSGID, "", paramSSHSGIDDefault, paramSSHSGIDDesc)
305+
flagSet.StringP(paramTicket, "", paramTicketDefault, paramTicketDesc)
258306
flagSet.Bool(params.Serverless, false, params.ServerlessDesc)
259307
flagSet.Bool(params.Remote, false, params.RemoteDesc)
260308
c.PersistentFlags().AddFlagSet(flagSet)
261-
err := c.MarkPersistentFlagRequired(awsParams.MACDHID)
262-
if err != nil {
263-
logging.Error(err)
264-
}
265309
return c
266310
}

go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ module github.com/redhat-developer/mapt
22

33
go 1.23.1
44

5-
toolchain go1.24.2
5+
toolchain go1.23.7
66

77
require (
88
github.com/coocood/freecache v1.2.4

pkg/provider/aws/action/mac-pool/housekeeper.go

Lines changed: 98 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -2,33 +2,38 @@ package macpool
22

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

67
maptContext "github.com/redhat-developer/mapt/pkg/manager/context"
78
"github.com/redhat-developer/mapt/pkg/provider/aws"
8-
"github.com/redhat-developer/mapt/pkg/provider/aws/modules/serverless"
9+
"github.com/redhat-developer/mapt/pkg/provider/aws/modules/mac"
10+
macHost "github.com/redhat-developer/mapt/pkg/provider/aws/modules/mac/host"
11+
"github.com/redhat-developer/mapt/pkg/util"
912
"github.com/redhat-developer/mapt/pkg/util/logging"
1013
)
1114

1215
// House keeper is the function executed serverless to check if is there any
1316
// machine non locked which had been running more than 24h.
1417
// It should check if capacity allows to remove the machine
15-
func houseKeeper(ctx *maptContext.ContextArgs, r *MacPoolRequestArgs) error {
18+
func houseKeeper(ctx *maptContext.ContextArgs, r *HouseKeepRequestArgs) error {
1619
// Create mapt Context, this is a special case where we need change the context
1720
// based on the operation
1821
if err := maptContext.Init(ctx, aws.Provider()); err != nil {
1922
return err
2023
}
21-
2224
// Get full info on the pool
23-
p, err := getPool(r.PoolName, r.Architecture, r.OSVersion)
25+
p, err := getPool(r.Pool.Name, r.Pool.Architecture, r.Pool.OSVersion)
2426
if err != nil {
2527
return err
2628
}
29+
p.maxSize = r.Pool.MaxSize
30+
p.offeredCapacity = r.Pool.OfferedCapacity
31+
logging.Debugf("Current pool: %s", p.print())
2732
// Pool under expected offered capacity
28-
if p.currentOfferedCapacity() < r.OfferedCapacity {
29-
if p.currentPoolSize() < r.MaxSize {
33+
if p.currentOfferedCapacity() < r.Pool.OfferedCapacity {
34+
if p.currentPoolSize() < r.Pool.MaxSize {
3035
logging.Debug("house keeper will try to add machines as offered capacity is lower than expected")
31-
maptContext.SetProjectName(r.PoolName)
36+
maptContext.SetProjectName(r.Pool.Name)
3237
return r.addCapacity(p)
3338
}
3439
// if number of machines in the pool + to max machines
@@ -37,7 +42,7 @@ func houseKeeper(ctx *maptContext.ContextArgs, r *MacPoolRequestArgs) error {
3742
return nil
3843
}
3944
// Pool over expected offered capacity need to destroy machines
40-
if p.currentOfferedCapacity() > r.OfferedCapacity {
45+
if p.currentOfferedCapacity() > r.Pool.OfferedCapacity {
4146
if len(p.destroyableMachines) > 0 {
4247
logging.Debug("house keeper will try to destroy machines as offered capacity is higher than expected")
4348
// Need to check if any offered can be destroy
@@ -49,37 +54,92 @@ func houseKeeper(ctx *maptContext.ContextArgs, r *MacPoolRequestArgs) error {
4954
return nil
5055
}
5156

52-
// Run serverless operation for house keeping
53-
func (r *MacPoolRequestArgs) scheduleHouseKeeper() error {
54-
return serverless.Create(
55-
&serverless.ServerlessArgs{
56-
ContainerName: fmt.Sprintf("housekeeper-%s-%s-%s",
57-
r.PoolName,
58-
r.Architecture,
59-
r.OSVersion),
60-
Command: houseKeepingCommand(
61-
r.PoolName,
62-
r.Architecture,
63-
r.OSVersion,
64-
r.OfferedCapacity,
65-
r.MaxSize,
66-
r.FixedLocation),
67-
ScheduleType: &serverless.Repeat,
68-
Schedulexpression: houseKeepingInterval,
69-
LogGroupName: fmt.Sprintf("%s-%s-%s",
70-
r.PoolName,
71-
r.Architecture,
72-
r.OSVersion)})
57+
func (r *HouseKeepRequestArgs) addMachinesToPool(n int) error {
58+
if err := validateBackedURL(); err != nil {
59+
return err
60+
}
61+
for i := 0; i < n; i++ {
62+
hr := r.fillHostRequest()
63+
dh, err := macHost.CreatePoolDedicatedHost(hr)
64+
if err != nil {
65+
return err
66+
}
67+
mr := r.fillMacRequest()
68+
if err = mr.CreateAvailableMacMachine(dh); err != nil {
69+
return err
70+
}
71+
}
72+
return nil
73+
}
74+
75+
// format for remote backed url when creating the dedicated host
76+
// the backed url from param is used as base and the ID is appended as sub path
77+
func validateBackedURL() error {
78+
if strings.Contains(maptContext.BackedURL(), "file://") {
79+
return fmt.Errorf("local backed url is not allowed for mac pool")
80+
}
81+
return nil
82+
}
83+
84+
// transform pool request to host request
85+
// need if we need to expand the pool
86+
func (r *HouseKeepRequestArgs) fillHostRequest() *macHost.PoolMacDedicatedHostRequestArgs {
87+
return &macHost.PoolMacDedicatedHostRequestArgs{
88+
MacDedicatedHost: &macHost.MacDedicatedHostRequestArgs{
89+
Prefix: r.Pool.Prefix,
90+
Architecture: r.Pool.Architecture,
91+
// FixedLocation: r.FixedLocation,
92+
VPCID: &r.Machine.VPCID,
93+
AZID: &r.Machine.AZID,
94+
SubnetID: &r.Machine.SubnetID,
95+
SSHSGID: &r.Machine.SSHSGID,
96+
},
97+
PoolID: &macHost.PoolID{
98+
PoolName: r.Pool.Name,
99+
Arch: r.Pool.Architecture,
100+
OSVersion: r.Pool.OSVersion,
101+
},
102+
BackedURL: fmt.Sprintf("%s/%s",
103+
maptContext.BackedURL(),
104+
util.RandomID("mapt")),
105+
}
106+
}
107+
108+
// If we need less or equal than the max allowed on the pool we create all of them
109+
// if need are more than allowed we can create just the allowed
110+
func (r *HouseKeepRequestArgs) addCapacity(p *pool) error {
111+
machinesToAdd := p.offeredCapacity - p.currentOfferedCapacity()
112+
if machinesToAdd+p.currentPoolSize() > p.maxSize {
113+
machinesToAdd = p.maxSize - p.currentPoolSize()
114+
}
115+
logging.Debugf("Adding %d machines", machinesToAdd)
116+
return r.addMachinesToPool(machinesToAdd)
73117
}
74118

75-
func houseKeepingCommand(poolName, arch, osVersion string,
76-
offeredCapacity, maxSize int,
77-
fixedLocation bool) string {
78-
cmd := fmt.Sprintf(houseKeepingCommandRegex,
79-
poolName, arch, osVersion,
80-
offeredCapacity, maxSize)
81-
if fixedLocation {
82-
cmd += houseKeepingFixedLocationParam
119+
// If we need less or equal than the max allowed on the pool we create all of them
120+
// if need are more than allowed we can create just the allowed
121+
// TODO review allocation time is on the wrong order
122+
func (r *HouseKeepRequestArgs) destroyCapacity(p *pool) error {
123+
machinesToDestroy := p.currentOfferedCapacity() - r.Pool.OfferedCapacity
124+
for i := 0; i < machinesToDestroy; i++ {
125+
m := p.destroyableMachines[i]
126+
// TODO change this
127+
maptContext.SetProjectName(*m.ProjectName)
128+
if err := aws.DestroyStack(aws.DestroyStackRequest{
129+
Stackname: mac.StackMacMachine,
130+
Region: *m.Region,
131+
BackedURL: *m.BackedURL,
132+
}); err != nil {
133+
return err
134+
}
135+
if err := aws.DestroyStack(aws.DestroyStackRequest{
136+
Stackname: mac.StackDedicatedHost,
137+
// TODO check if needed to add region for backedURL
138+
Region: *m.Region,
139+
BackedURL: *m.BackedURL,
140+
}); err != nil {
141+
return err
142+
}
83143
}
84-
return cmd
144+
return nil
85145
}

0 commit comments

Comments
 (0)