Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
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
Original file line number Diff line number Diff line change
Expand Up @@ -615,6 +615,70 @@ describe('create runner', () => {
});
});

it('uses InstanceRequirements without static InstanceType overrides', async () => {
const instanceRequirements = {
VCpuCount: { Min: 4, Max: 8 },
MemoryMiB: { Min: 8192, Max: 16384 },
AllowedInstanceTypes: ['c7i.*', 'm7i.*'],
};

await createRunner({
...createRunnerConfig(defaultRunnerConfig),
ec2OverrideConfig: { InstanceRequirements: instanceRequirements },
});

expect(mockEC2Client).toHaveReceivedCommandWith(CreateFleetCommand, {
LaunchTemplateConfigs: [
{
LaunchTemplateSpecification: {
LaunchTemplateName: 'lt-1',
Version: '$Default',
},
Overrides: [
{
InstanceRequirements: instanceRequirements,
SubnetId: 'subnet-123',
},
{
InstanceRequirements: instanceRequirements,
SubnetId: 'subnet-456',
},
],
},
],
SpotOptions: {
AllocationStrategy: SpotAllocationStrategy.CAPACITY_OPTIMIZED,
},
TagSpecifications: expect.any(Array),
TargetCapacitySpecification: {
DefaultTargetCapacityType: 'spot',
TotalTargetCapacity: 1,
},
Type: 'instant',
});
});

it('rejects conflicting InstanceType and InstanceRequirements overrides', async () => {
await expect(
createRunner({
...createRunnerConfig(defaultRunnerConfig),
ec2OverrideConfig: {
InstanceType: 'c7i.xlarge',
InstanceRequirements: {
VCpuCount: { Min: 4 },
MemoryMiB: { Min: 8192 },
},
},
}),
).resolves.toEqual({
instances: [],
retryableErrorCount: 0,
nonRetryableErrorCount: 1,
});

expect(mockEC2Client).not.toHaveReceivedCommand(CreateFleetCommand);
});

it('overrides ImageId when specified in ec2OverrideConfig', async () => {
await createRunner({
...createRunnerConfig(defaultRunnerConfig),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -220,11 +220,24 @@ function generateFleetOverrides(
): FleetLaunchTemplateOverridesRequest[] {
const result: FleetLaunchTemplateOverridesRequest[] = [];

if (ec2OverrideConfig?.InstanceType && ec2OverrideConfig.InstanceRequirements) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Good catch. This works fine here for now. But if we need more validations like this one, this will get smelly.
To prevent a refactor in the future, lets create a validation function in /lambdas/libs/compute-providers/aws/ec2/src/control-plane/dynamic-labels.ts, there we can add the config validations, including this one

And in lambdas/libs/compute-providers/aws/ec2/src/control-plane/scale-up.ts we call the validation

    ec2OverrideConfig = parseEc2OverrideConfig(dynamicEC2Labels, defaultBlockDeviceName);
    if (ec2OverrideConfig) {
      logger.debug('EC2 override config parsed from labels', { ec2OverrideConfig });
    }
    <call validation function> with ec2OverrideConfig

throw new Error('InstanceType and InstanceRequirements cannot be used together');
}

// Use override values if available, otherwise use parameter arrays
const subnetsToUse = ec2OverrideConfig?.SubnetId ? [ec2OverrideConfig.SubnetId] : subnetIds;
const instanceTypesToUse = ec2OverrideConfig?.InstanceType ? [ec2OverrideConfig.InstanceType] : instancesTypes;
const amiIdToUse = ec2OverrideConfig?.ImageId ?? amiId;

if (ec2OverrideConfig?.InstanceRequirements) {
return subnetsToUse.map((subnetId) => ({
SubnetId: subnetId,
ImageId: amiIdToUse,
...ec2OverrideConfig,
}));
}
Comment on lines +232 to +237

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Could we explicitly type the map callback return as FleetLaunchTemplateOverridesRequest, consistent with the item declaration below? The current code is type-safe through the function return annotation, but the explicit annotation makes the request contract clearer.


const instanceTypesToUse = ec2OverrideConfig?.InstanceType ? [ec2OverrideConfig.InstanceType] : instancesTypes;

// Both the on-demand 'prioritized' and the spot 'capacity-optimized-prioritized' strategies
// honor the Priority field of the launch template overrides.
const usesPriority = allocationStrategy === 'prioritized' || allocationStrategy === 'capacity-optimized-prioritized';
Expand Down
Loading