Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion cmd/mapt/cmd/aws/hosts/fedora.go
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,8 @@ func getFedoraCreate() *cobra.Command {
Spot: params.SpotArgs(),
Timeout: viper.GetString(params.Timeout),
Airgap: viper.IsSet(airgap),
ServiceEndpoints: params.NetworkServiceEndpoints()})
ServiceEndpoints: params.NetworkServiceEndpoints(),
VpcID: params.NetworkVpcID()})
},
}
flagSet := pflag.NewFlagSet(params.CreateCmdName, pflag.ExitOnError)
Expand Down
1 change: 1 addition & 0 deletions cmd/mapt/cmd/aws/hosts/rhel.go
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ func getRHELCreate() *cobra.Command {
Timeout: viper.GetString(params.Timeout),
Airgap: viper.IsSet(airgap),
ServiceEndpoints: params.NetworkServiceEndpoints(),
VpcID: params.NetworkVpcID(),
})
},
}
Expand Down
1 change: 1 addition & 0 deletions cmd/mapt/cmd/aws/hosts/rhelai.go
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ func getRHELAICreate() *cobra.Command {
AutoStart: viper.IsSet(params.RhelAIAutoStart),
VLLMExtraArgs: viper.GetString(params.RhelAIVLLMExtraArgs),
ExposePorts: viper.GetIntSlice(params.RhelAIExposePorts),
VpcID: params.NetworkVpcID(),
})
},
}
Expand Down
1 change: 1 addition & 0 deletions cmd/mapt/cmd/aws/hosts/windows.go
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ func getWindowsCreate() *cobra.Command {
Airgap: viper.IsSet(airgap),
Timeout: viper.GetString(params.Timeout),
ServiceEndpoints: params.NetworkServiceEndpoints(),
VpcID: params.NetworkVpcID(),
})
},
}
Expand Down
13 changes: 12 additions & 1 deletion cmd/mapt/cmd/params/params.go
Original file line number Diff line number Diff line change
Expand Up @@ -205,7 +205,9 @@ const (
KindExtraPortMappingsDesc = "Additional port mappings for the Kind cluster. Value should be a JSON array of objects with containerPort, hostPort, and protocol properties. Example: '[{\"containerPort\": 8080, \"hostPort\": 8080, \"protocol\": \"TCP\"}]'"

// Network
ServiceEndpoints = "service-endpoints"
ServiceEndpoints = "service-endpoints"
VpcID = "vpc-id"
VpcIDDesc = "ID of an existing VPC to deploy the instance into. When set, airgap is not supported and spot search is restricted to AZs with subnets in that VPC."

// Spot
spot = "spot"
Expand All @@ -222,12 +224,21 @@ const (

func AddNetworkFlags(fs *pflag.FlagSet, desc string) {
fs.StringSliceP(ServiceEndpoints, "", []string{}, desc)
fs.StringP(VpcID, "", "", VpcIDDesc)
}

func NetworkServiceEndpoints() []string {
return viper.GetStringSlice(ServiceEndpoints)
}

func NetworkVpcID() *string {
if viper.IsSet(VpcID) {
v := viper.GetString(VpcID)
return &v
}
return nil
}
Comment on lines +234 to +240

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Empty-string --vpc-id treated as “set”.

viper.IsSet returns true once the flag is Changed, even if the value is "" (e.g. --vpc-id="$VPC_ID" with an unset env var in a CI script). NetworkVpcID() then returns a pointer to "" instead of nil, and downstream (NetworkArgs.VpcID != nil) will route into existingVPCNetwork and call ec2.GetVpc with an empty ID, failing deep in the Pulumi provider instead of failing fast with a clear message.

🔧 Proposed fix
 func NetworkVpcID() *string {
-	if viper.IsSet(VpcID) {
-		v := viper.GetString(VpcID)
-		return &v
-	}
-	return nil
+	if v := viper.GetString(VpcID); v != "" {
+		return &v
+	}
+	return nil
 }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
func NetworkVpcID() *string {
if viper.IsSet(VpcID) {
v := viper.GetString(VpcID)
return &v
}
return nil
}
func NetworkVpcID() *string {
if v := viper.GetString(VpcID); v != "" {
return &v
}
return nil
}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@cmd/mapt/cmd/params/params.go` around lines 234 - 240, `NetworkVpcID()`
currently treats an empty `--vpc-id` as present because it relies on
`viper.IsSet`, which can return true for a changed-but-empty flag. Update the
`NetworkVpcID` helper in `params.go` to return nil when the resolved VPC ID is
empty (or whitespace) so `NetworkArgs.VpcID` does not route into
`existingVPCNetwork` with an invalid ID. Use the `VpcID` flag lookup in
`NetworkVpcID` as the single place to normalize this behavior before downstream
calls like `ec2.GetVpc`.


func AddSpotFlags(fs *pflag.FlagSet) {
fs.Bool(spot, false, spotDesc)
fs.StringP(spotTolerance, "", spotToleranceDefault, spotToleranceDesc)
Expand Down
40 changes: 24 additions & 16 deletions pkg/provider/aws/action/fedora/fedora.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,28 +33,30 @@ import (
)

type FedoraArgs struct {
Prefix string
Version string
Arch string
ComputeRequest *cr.ComputeRequestArgs
Spot *spotTypes.SpotArgs
Airgap bool
Prefix string
Version string
Arch string
ComputeRequest *cr.ComputeRequestArgs
Spot *spotTypes.SpotArgs
Airgap bool
ServiceEndpoints []string
VpcID *string
// If timeout is set a severless scheduled task will be created to self destroy the resources
Timeout string
}

type fedoraRequest struct {
mCtx *mc.Context
prefix *string
version *string
arch *string
spot bool
timeout *string
mCtx *mc.Context
prefix *string
version *string
arch *string
spot bool
timeout *string
serviceEndpoints []string
allocationData *allocation.AllocationResult
airgap *bool
diskSize *int
vpcID *string
allocationData *allocation.AllocationResult
airgap *bool
diskSize *int
// internal management
// For airgap scenario there is an orchestation of
// a phase with connectivity on the machine (allowing bootstraping)
Expand All @@ -81,6 +83,9 @@ func Create(mCtxArgs *mc.ContextArgs, args *FedoraArgs) (err error) {
return err
}
// Compose request
if args.VpcID != nil && args.Airgap {
return fmt.Errorf("--vpc-id and --airgap are mutually exclusive")
}
prefix := util.If(len(args.Prefix) > 0, args.Prefix, "main")
r := fedoraRequest{
mCtx: mCtx,
Expand All @@ -89,6 +94,7 @@ func Create(mCtxArgs *mc.ContextArgs, args *FedoraArgs) (err error) {
arch: &args.Arch,
timeout: &args.Timeout,
serviceEndpoints: args.ServiceEndpoints,
vpcID: args.VpcID,
airgap: &args.Airgap,
diskSize: args.ComputeRequest.DiskSize}
if args.Spot != nil {
Expand All @@ -100,6 +106,7 @@ func Create(mCtxArgs *mc.ContextArgs, args *FedoraArgs) (err error) {
ComputeRequest: args.ComputeRequest,
AMIProductDescription: &amiProduct,
Spot: args.Spot,
VpcID: args.VpcID,
})
if err != nil {
return err
Expand Down Expand Up @@ -201,7 +208,8 @@ func (r *fedoraRequest) deploy(ctx *pulumi.Context) error {
CreateLoadBalancer: r.spot,
Airgap: *r.airgap,
AirgapPhaseConnectivity: r.airgapPhaseConnectivity,
ServiceEndpoints: r.serviceEndpoints,
ServiceEndpoints: r.serviceEndpoints,
VpcID: r.vpcID,
})
if err != nil {
return err
Expand Down
4 changes: 4 additions & 0 deletions pkg/provider/aws/action/rhel-ai/rhelai.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ type rhelAIRequest struct {
spot bool
timeout *string
serviceEndpoints []string
vpcID *string
allocationData *allocation.AllocationResult
diskSize *int
model *string
Expand Down Expand Up @@ -81,6 +82,7 @@ func Create(mCtxArgs *mc.ContextArgs, args *apiRHELAI.RHELAIArgs) (err error) {
arch: &args.Arch,
timeout: &args.Timeout,
serviceEndpoints: args.ServiceEndpoints,
vpcID: args.VpcID,
diskSize: args.ComputeRequest.DiskSize,
model: &args.Model,
hfToken: &args.HFToken,
Expand All @@ -97,6 +99,7 @@ func Create(mCtxArgs *mc.ContextArgs, args *apiRHELAI.RHELAIArgs) (err error) {
ComputeRequest: args.ComputeRequest,
AMIProductDescription: &amiProduct,
Spot: args.Spot,
VpcID: args.VpcID,
})
if err != nil {
return err
Expand Down Expand Up @@ -228,6 +231,7 @@ func (r *rhelAIRequest) deploy(ctx *pulumi.Context) error {
AZ: *r.allocationData.AZ,
CreateLoadBalancer: r.allocationData.SpotPrice != nil,
ServiceEndpoints: r.serviceEndpoints,
VpcID: r.vpcID,
})
if err != nil {
return err
Expand Down
10 changes: 9 additions & 1 deletion pkg/provider/aws/action/rhel/rhel.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ type RHELArgs struct {
Spot *spotTypes.SpotArgs
Airgap bool
ServiceEndpoints []string
VpcID *string
// If timeout is set a severless scheduled task will be created to self destroy the resources
Timeout string
}
Expand All @@ -57,6 +58,7 @@ type rhelRequest struct {
profileSNC *bool
timeout *string
serviceEndpoints []string
vpcID *string
allocationData *allocation.AllocationResult
airgap *bool
diskSize *int
Expand Down Expand Up @@ -86,6 +88,9 @@ func Create(mCtxArgs *mc.ContextArgs, args *RHELArgs) (err error) {
return err
}
// Compose request
if args.VpcID != nil && args.Airgap {
return fmt.Errorf("--vpc-id and --airgap are mutually exclusive")
}
prefix := util.If(len(args.Prefix) > 0, args.Prefix, "main")
r := rhelRequest{
mCtx: mCtx,
Expand All @@ -97,6 +102,7 @@ func Create(mCtxArgs *mc.ContextArgs, args *RHELArgs) (err error) {
subsUserpass: &args.SubsUserpass,
profileSNC: &args.ProfileSNC,
serviceEndpoints: args.ServiceEndpoints,
vpcID: args.VpcID,
airgap: &args.Airgap,
diskSize: args.ComputeRequest.DiskSize}
if args.Spot != nil {
Expand All @@ -108,6 +114,7 @@ func Create(mCtxArgs *mc.ContextArgs, args *RHELArgs) (err error) {
ComputeRequest: args.ComputeRequest,
AMIProductDescription: &amiProduct,
Spot: args.Spot,
VpcID: args.VpcID,
})
if err != nil {
return err
Expand Down Expand Up @@ -206,7 +213,8 @@ func (r *rhelRequest) deploy(ctx *pulumi.Context) error {
CreateLoadBalancer: r.allocationData.SpotPrice != nil,
Airgap: *r.airgap,
AirgapPhaseConnectivity: r.airgapPhaseConnectivity,
ServiceEndpoints: r.serviceEndpoints,
ServiceEndpoints: r.serviceEndpoints,
VpcID: r.vpcID,
})
if err != nil {
return err
Expand Down
26 changes: 17 additions & 9 deletions pkg/provider/aws/action/windows/windows.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,10 +46,11 @@ type WindowsServerArgs struct {
AMILang string
AMIKeepCopy bool
// Machine params
ComputeRequest *cr.ComputeRequestArgs
Spot *spotTypes.SpotArgs
Airgap bool
ComputeRequest *cr.ComputeRequestArgs
Spot *spotTypes.SpotArgs
Airgap bool
ServiceEndpoints []string
VpcID *string
// If timeout is set a severless scheduled task will be created to self destroy the resources
Timeout string
}
Expand All @@ -64,12 +65,13 @@ type windowsServerRequest struct {
amiLang *string
amiKeepCopy *bool

spot bool
timeout *string
spot bool
timeout *string
serviceEndpoints []string
allocationData *allocation.AllocationResult
airgap *bool
diskSize *int
vpcID *string
allocationData *allocation.AllocationResult
airgap *bool
diskSize *int
// internal management
// For airgap scenario there is an orchestation of
// a phase with connectivity on the machine (allowing bootstraping)
Expand Down Expand Up @@ -104,6 +106,9 @@ func Create(mCtxArgs *mc.ContextArgs, args *WindowsServerArgs) (err error) {
args.AMIName = amiNonEngNameDefault
}
// Compose request
if args.VpcID != nil && args.Airgap {
return fmt.Errorf("--vpc-id and --airgap are mutually exclusive")
}
prefix := util.If(len(args.Prefix) > 0, args.Prefix, "main")
r := windowsServerRequest{
mCtx: mCtx,
Expand All @@ -115,6 +120,7 @@ func Create(mCtxArgs *mc.ContextArgs, args *WindowsServerArgs) (err error) {
amiLang: &args.AMILang,
timeout: &args.Timeout,
serviceEndpoints: args.ServiceEndpoints,
vpcID: args.VpcID,
airgap: &args.Airgap,
}
if args.ComputeRequest != nil {
Expand All @@ -129,6 +135,7 @@ func Create(mCtxArgs *mc.ContextArgs, args *WindowsServerArgs) (err error) {
ComputeRequest: args.ComputeRequest,
AMIProductDescription: &amiProduct,
Spot: args.Spot,
VpcID: args.VpcID,
})
if err != nil {
return err
Expand Down Expand Up @@ -259,7 +266,8 @@ func (r *windowsServerRequest) deploy(ctx *pulumi.Context) error {
CreateLoadBalancer: r.spot,
Airgap: *r.airgap,
AirgapPhaseConnectivity: r.airgapPhaseConnectivity,
ServiceEndpoints: r.serviceEndpoints,
ServiceEndpoints: r.serviceEndpoints,
VpcID: r.vpcID,
})
if err != nil {
return err
Expand Down
28 changes: 19 additions & 9 deletions pkg/provider/aws/data/azs.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,19 +42,28 @@ type AvailabilityZonesResult struct {
Err error
}

func describeAvailabilityZonesAsync(ctx context.Context, regionName string, c chan AvailabilityZonesResult) {
data, err := DescribeAvailabilityZones(ctx, regionName)
c <- AvailabilityZonesResult{
AvailabilityZones: data,
Err: err}

func describeAvailabilityZonesAllAsync(ctx context.Context, regionName string, c chan AvailabilityZonesResult) {
data, err := describeAvailabilityZonesAll(ctx, regionName)
c <- AvailabilityZonesResult{AvailabilityZones: data, Err: err}
}

func DescribeAvailabilityZones(ctx context.Context, regionName string) ([]ec2Types.AvailabilityZone, error) {
return describeAvailabilityZones(ctx, regionName, nil)
}

func describeAvailabilityZones(ctx context.Context, regionName string, excludedZoneIDs []string) ([]ec2Types.AvailabilityZone, error) {
return describeAvailabilityZonesOpts(ctx, regionName, excludedZoneIDs, false)
}

// describeAvailabilityZonesAll is like describeAvailabilityZones but includes AZs not
// normally visible to the account (AllAvailabilityZones: true). Used only for AZ ID→name
// resolution during spot placement score lookups, where the scores API can return AZ IDs
// for zones not yet opted-in to by the account.
func describeAvailabilityZonesAll(ctx context.Context, regionName string) ([]ec2Types.AvailabilityZone, error) {
return describeAvailabilityZonesOpts(ctx, regionName, nil, true)
}

func describeAvailabilityZonesOpts(ctx context.Context, regionName string, excludedZoneIDs []string, allZones bool) ([]ec2Types.AvailabilityZone, error) {
var cfgOpts config.LoadOptionsFunc
if len(regionName) > 0 {
cfgOpts = config.WithRegion(regionName)
Expand All @@ -64,9 +73,8 @@ func describeAvailabilityZones(ctx context.Context, regionName string, excludedZ
return nil, err
}
client := ec2.NewFromConfig(cfg)
// TODO check what happen when true and region name
input := ec2.DescribeAvailabilityZonesInput{
// AllAvailabilityZones: aws.Bool(true),
AllAvailabilityZones: aws.Bool(allZones),
}
input.Filters = []ec2Types.Filter{
{
Expand Down Expand Up @@ -112,12 +120,14 @@ func getZoneName(azID string, azDescriptions []ec2Types.AvailabilityZone) (strin
// user 1 Name: us-west-1a ID: us-west-11, Name: us-west-1b ID: us-west-12
// user 2 Name: us-west-1a ID: us-west-12, Name: us-west-1b ID: us-west-11
// This allowsa a better distribution among users
// describeAvailabilityZonesByRegions fetches all AZs (including non-opted-in ones) so
// that AZ IDs returned by GetSpotPlacementScores can always be resolved to names.
func describeAvailabilityZonesByRegions(ctx context.Context, regions []string) map[string][]ec2Types.AvailabilityZone {
result := make(map[string][]ec2Types.AvailabilityZone)
c := make(chan AvailabilityZonesResult)
for _, region := range regions {
lRegion := region
go describeAvailabilityZonesAsync(ctx, lRegion, c)
go describeAvailabilityZonesAllAsync(ctx, lRegion, c)
}
for i := 0; i < len(regions); i++ {
availabilityZonesResult := <-c
Expand Down
Loading