Skip to content

feat(aws): add --instance-families flag to filter compute selector output - #872

Open
amastbau wants to merge 8 commits into
redhat-developer:mainfrom
amastbau:feat/instance-families
Open

feat(aws): add --instance-families flag to filter compute selector output#872
amastbau wants to merge 8 commits into
redhat-developer:mainfrom
amastbau:feat/instance-families

Conversation

@amastbau

@amastbau amastbau commented Jul 29, 2026

Copy link
Copy Markdown

Summary

Adds --compute-families flag (comma-separated allowlist of family prefixes, e.g. m5,m6i,m7i for AWS) that post-filters the compute selector output to only matching families.

Renamed from --instance-families to --compute-families per @adrianriobo review comment to support Azure (which uses family-based naming like StandardD8v3Family).

Fixes #684

Problem

When using --cpus and --memory, the instance selector returns up to 20 types including expensive specialized families (d3en, p3, x1e — dense storage, GPU, high-memory) alongside cheap general-purpose ones. Spot picks the cheapest at that moment, which may be a temporarily cheap specialized instance. Example: d3en.12xlarge and m5a.12xlarge have identical vCPU/Memory but the former is ~3x more expensive.

Changes

  • pkg/provider/api/compute-request/compute-request.go — add ComputeFamilies []string field to ComputeRequestArgs with AWS and Azure examples in doc comment
  • pkg/provider/aws/data/compute-request.go — extract filterByFamily() helper; skip MaxResults cap in selector when family filter active; apply cap manually after filtering
  • pkg/provider/aws/data/compute-request_test.go — 8 unit tests for filterByFamily() including cap-after-filter regression
  • cmd/mapt/cmd/params/params.go — add --compute-families flag, populate field
  • tkn/template/infra-aws-ocp-snc.yaml, tkn/template/infra-aws-rhel.yaml — add compute-families param; pass flag in else branch of compute-sizes conditional
  • Regenerated tkn/infra-aws-ocp-snc.yaml, tkn/infra-aws-rhel.yaml

Behavior

  • --compute-families m5,m6i,m7i → selector returns only m5.*, m6i.*, m7i.* types
  • --compute-families is a no-op when --compute-sizes is set (compute-sizes bypasses the selector entirely — Tekton template also gates the param in the else branch)
  • Empty --compute-families (default) → no restriction, existing behavior unchanged
  • Filter uses dot-separator check (strings.HasPrefix(t, fam+".")) so m5 does not match m5a

Cross-cloud naming

  • AWS: family is prefix before dot (e.g. m5 in m5.xlarge, c6i in c6i.2xlarge)
  • Azure: family is in SKU Family field with "Family" suffix (e.g. StandardD8v3Family, StandardE16v4Family)
  • User passes prefix without "Family" suffix: --compute-families D8v3,E16v4

Cap fix

When ComputeFamilies is set, MaxResults is no longer passed to FilterVerbose. Without this fix, the selector could return 20 results all outside the allowlist (e.g. GPU/storage types ranked highest), leaving nothing after filterByFamily even though matching types exist beyond position 20. The cap is now applied after filtering.

Verification — AWS E2E

Unit tests (8/8 pass)

cd pkg/provider/aws/data && go test -v --tags build -run TestFilterByFamily

All tests pass including:

  • Dot-separator enforcement (m5 excludes m5a)
  • Cap applied after filter (not before)
  • Empty families returns all types

Live AWS API test (ComputeSelector with real DescribeInstanceTypes)

Test 1: 4 vCPU / 16 GiB with --compute-families m5,m6i

selector.Select(ComputeFamilies: [m5, m6i]) → [m5.xlarge, m6i.xlarge]
✓ PASS: Only m5.* and m6i.* types returned
✓ PASS: m5a.xlarge correctly excluded (dot-separator enforced)

Test 2: 4 vCPU / 16 GiB with --compute-families m5 only

selector.Select(ComputeFamilies: [m5]) → [m5.xlarge]
✓ PASS: m5a family correctly excluded

Full E2E (mapt CLI → EC2 provision → destroy)

mapt aws rhel create \
  --cpus 4 --memory 16 \
  --compute-families m5,m6i \
  --project-name test-families-e2e \
  --backed-url file:///tmp/mapt-state

Results:

  • ✓ Debug log: Requesting an on-demand instance of type: m5.xlarge
  • ✓ AWS API verification: Instance i-0919271674561e88e type m5.xlarge created
  • ✓ Instance provisioned, SSH reachable
  • ✓ Destroyed cleanly (14 resources)

No GPU or storage-optimized type selected — filter worked correctly in full provision flow.

Comparison (no filter vs with filter)

Without --compute-families (4 vCPU / 16 GiB):

d3en.xlarge   ← dense storage (~3x cost)
g4ad.xlarge   ← GPU
g4dn.xlarge   ← GPU
g5.xlarge     ← GPU
g6.xlarge     ← GPU
g6f.xlarge    ← GPU
inf2.xlarge   ← ML inference
m4.xlarge
m5.xlarge
m5a.xlarge
m5ad.xlarge
m5d.xlarge
m5dn.xlarge
m5n.xlarge
m5zn.xlarge
m6a.xlarge
m6i.xlarge
m6id.xlarge
m6idn.xlarge
m6in.xlarge
(20 types total)

With --compute-families m5,m6i:

m5.xlarge
m6i.xlarge
(2 types, both general-purpose)

🤖 Generated with Claude Code

Amos Mastbaum added 3 commits July 30, 2026 00:07
Post-filters getInstanceTypes() output to only instance types whose
family prefix matches the allowlist. Bypassed when ComputeSizes is set.

Fixes: redhat-developer#684
Comma-separated allowlist of AWS family prefixes (e.g. m5,m6i,m7i).
Post-filters instance selector output. No-op when --compute-sizes is set.
Passes --instance-families to mapt when set. Conditional: only in the
else branch (when compute-sizes is empty) since compute-sizes bypasses
the selector entirely.
@coderabbitai

coderabbitai Bot commented Jul 29, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Summary by CodeRabbit

  • New Features
    • Added an optional AWS compute-family allowlist using comma-separated family prefixes such as m5 or c6i.
    • Exposed compute-families in CLI and Tekton provisioning tasks; it applies when specific compute sizes are not provided.
  • Bug Fixes
    • Ensured matching instance types are filtered before applying the requested maximum, preventing eligible options from being omitted.
  • Tests
    • Added coverage for empty inputs, single and multiple families, exact prefix matching, fully filtered results, and result limits.

Walkthrough

Adds an optional AWS compute-family allowlist to compute request arguments. AWS instance types use exact family-prefix matching. CLI and Tekton create commands pass the allowlist only when compute-sizes is unset.

Changes

Instance-family filtering

Layer / File(s) Summary
Request contract and CLI wiring
pkg/provider/api/compute-request/compute-request.go, cmd/mapt/cmd/params/params.go
Adds ComputeFamilies and maps the --compute-families string-slice flag into compute request arguments.
AWS instance-family filtering
pkg/provider/aws/data/compute-request.go, pkg/provider/aws/data/compute-request_test.go
Filters types by exact family prefixes and applies MaxResults after filtering. Tests cover empty, single-family, multi-family, unmatched, nil-input, and result-cap cases.
Tekton provisioning wiring
tkn/infra-aws-*.yaml, tkn/template/infra-aws-*.yaml
Adds the optional parameter and conditionally appends --compute-families during create operations when compute-sizes is unset.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Sequence Diagram(s)

sequenceDiagram
  participant TektonTask
  participant MaptCLI
  participant ComputeRequest
  participant AWSInstanceSelector

  TektonTask->>MaptCLI: Pass --compute-families during create
  MaptCLI->>ComputeRequest: Populate ComputeFamilies
  ComputeRequest->>AWSInstanceSelector: Request instance types
  AWSInstanceSelector->>AWSInstanceSelector: Filter exact family prefixes
  AWSInstanceSelector-->>ComputeRequest: Return filtered types capped by MaxResults
Loading

Suggested reviewers: jangel97, ppitonak

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Description check ✅ Passed The description clearly explains the compute-family filtering feature, its behavior, tests, and linked issue.
Linked Issues check ✅ Passed The description references issue #684, and the changes directly address its compute-selection problem.
Out of Scope Changes check ✅ Passed The changes are limited to compute-family filtering, tests, CLI parameters, and related AWS Tekton templates.
Title check ✅ Passed The title describes the AWS compute-family filtering change, although it uses the renamed flag name --instance-families.

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🤖 Prompt for all review comments with 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.

Inline comments:
In `@pkg/provider/aws/data/compute-request.go`:
- Line 52: Update the compute request filtering flow around filterByFamily so
InstanceFamilies is applied before MaxResults truncates selector results. When
args.InstanceFamilies is provided, avoid the premature cap or expand it
sufficiently while filtering the allowlisted families, then apply the requested
result limit to the filtered set.

In `@tkn/template/infra-aws-ocp-snc.yaml`:
- Around line 268-270: Stop interpolating the externally supplied
instance-families value into the eval-based command construction; build the
command as an argument list and invoke it directly with safe quoting or a Bash
array. Apply the fix to tkn/template/infra-aws-ocp-snc.yaml lines 268-270, then
regenerate or apply the equivalent change to tkn/infra-aws-ocp-snc.yaml lines
268-270; make the same change in tkn/template/infra-aws-rhel.yaml lines 283-285
and tkn/infra-aws-rhel.yaml lines 283-285.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: b3182e54-14b7-4474-af4a-489a865a6fdd

📥 Commits

Reviewing files that changed from the base of the PR and between 6e3cacf and 2d6ea43.

📒 Files selected for processing (8)
  • cmd/mapt/cmd/params/params.go
  • pkg/provider/api/compute-request/compute-request.go
  • pkg/provider/aws/data/compute-request.go
  • pkg/provider/aws/data/compute-request_test.go
  • tkn/infra-aws-ocp-snc.yaml
  • tkn/infra-aws-rhel.yaml
  • tkn/template/infra-aws-ocp-snc.yaml
  • tkn/template/infra-aws-rhel.yaml

Comment thread pkg/provider/aws/data/compute-request.go Outdated
Comment thread tkn/template/infra-aws-ocp-snc.yaml Outdated
Amos Mastbaum added 3 commits July 30, 2026 01:15
When InstanceFamilies is set, skip MaxResults in the selector so allowlisted
families ranked outside the top 20 are not silently dropped. Cap to MaxResults
manually after filterByFamily.
Exposes the --operator-channel CLI flag as a Tekton task param so
callers can override OLM subscription channels per operator.

Example: rhods-operator=stable-3.x to install RHOAI 3.x instead of
the default stable (2.25.x) channel.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
tkn/infra-aws-ocp-snc.yaml (1)

274-276: 🔒 Security & Privacy | 🟠 Major | ⚡ Quick win

Do not interpolate these parameters into an eval command.

The assembled command is executed with eval at Line 325. operator-channel is inserted unquoted, allowing values such as package=stable; ... to execute arbitrary shell commands; an apostrophe or command substitution in instance-families can similarly escape its wrapper. Because the task loads AWS credentials, this can expose credentials or alter provisioning.

Build the command as a Bash argument array and invoke it without eval, or strictly validate and shell-escape both parameters before appending them; also reject malformed package=channel entries.

As per path instructions, focus on major issues impacting security and avoid nitpicks and verbosity.

Also applies to: 294-299

🤖 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 `@tkn/infra-aws-ocp-snc.yaml` around lines 274 - 276, Replace the eval-based
command construction with a Bash argument array and invoke it directly,
preserving each parameter as a separate argument. Safely pass
params.instance-families and operator-channel without interpolation, and
validate operator-channel as a well-formed package=channel entry before
execution. Ensure malformed or unexpected values are rejected before the AWS
provisioning command runs.

Source: Path instructions

🤖 Prompt for all review comments with 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.

Outside diff comments:
In `@tkn/infra-aws-ocp-snc.yaml`:
- Around line 274-276: Replace the eval-based command construction with a Bash
argument array and invoke it directly, preserving each parameter as a separate
argument. Safely pass params.instance-families and operator-channel without
interpolation, and validate operator-channel as a well-formed package=channel
entry before execution. Ensure malformed or unexpected values are rejected
before the AWS provisioning command runs.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 27bc3a1f-0472-444d-8cfe-c8c48cdba136

📥 Commits

Reviewing files that changed from the base of the PR and between e2e4670 and 1e3f2a8.

📒 Files selected for processing (1)
  • tkn/infra-aws-ocp-snc.yaml

Verifies that allowlisted families ranked outside the top MaxResults
are not silently dropped when InstanceFamilies is set.

@ppitonak ppitonak left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Any reason not to update other infra-aws-* Tekton tasks?

Comment thread tkn/template/infra-aws-ocp-snc.yaml Outdated
@ppitonak

Copy link
Copy Markdown
Collaborator

I tested spot instances and it seems to work fine.

@amastbau
amastbau requested a review from ppitonak July 30, 2026 12:12
@amastbau

Copy link
Copy Markdown
Author

Any reason not to update other infra-aws-* Tekton tasks?

done!

Comment thread cmd/mapt/cmd/params/params.go Outdated
nestedVirtDesc string = "Use cloud instance that has nested virtualization support"
computeSizes string = "compute-sizes"
computeSizesDesc string = "Comma seperated list of sizes for the machines to be requested. If set this takes precedence over compute by args"
instanceFamilies string = "instance-families"

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Can we name it computeFamilies as this may / should have a matching functionality in azure?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

done.but i have not tested azure with the new code.not sure i have access.

@adrianriobo

Copy link
Copy Markdown
Collaborator

Aso rebase and fix conflicts

…ibility

Rename all references from instanceFamilies/InstanceFamilies to
computeFamilies/ComputeFamilies throughout codebase to support
Azure VM family naming (e.g. StandardD8v3Family).

Changes:
- pkg/provider/api/compute-request: ComputeFamilies field with AWS/Azure docs
- cmd/mapt/cmd/params: --compute-families flag and viper binding
- pkg/provider/aws/data: use ComputeFamilies in selector and filter
- tkn/template: compute-families param in SNC and RHEL tasks
- Regenerated tkn/*.yaml

Per @adrianriobo review comment on PR redhat-developer#872.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
@amastbau amastbau changed the title feat(aws): add --instance-families flag to filter instance selector output feat(aws): add --instance-families flag to filter compute selector output Jul 31, 2026

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🤖 Prompt for all review comments with 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.

Inline comments:
In `@pkg/provider/aws/data/compute-request_test.go`:
- Around line 58-79: Update TestFilterByFamily_CapAppliedAfterFilter to exercise
the production filter-and-cap path through getInstanceTypes, using a stubbed
selector or equivalent test setup. Configure computerequest.MaxResults and
assert that matching m6i values beyond the cap remain available, rather than
testing filterByFamily directly.

In `@tkn/infra-aws-ocp-snc.yaml`:
- Around line 268-270: Replace shared eval-based command construction at
tkn/infra-aws-ocp-snc.yaml lines 268-270, tkn/infra-aws-rhel.yaml lines 283-285,
and tkn/template/infra-aws-rhel.yaml lines 283-285 with argument-vector
handling: pass compute-families as a separate data argument, validate each
family token before execution, and preserve omission when the value is empty.
Apply the same change consistently in all three files.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: ab517f8b-016f-4e79-a9b3-5e51d1c2f644

📥 Commits

Reviewing files that changed from the base of the PR and between 1e3f2a8 and d88d78f.

📒 Files selected for processing (8)
  • cmd/mapt/cmd/params/params.go
  • pkg/provider/api/compute-request/compute-request.go
  • pkg/provider/aws/data/compute-request.go
  • pkg/provider/aws/data/compute-request_test.go
  • tkn/infra-aws-ocp-snc.yaml
  • tkn/infra-aws-rhel.yaml
  • tkn/template/infra-aws-ocp-snc.yaml
  • tkn/template/infra-aws-rhel.yaml
🚧 Files skipped from review as they are similar to previous changes (3)
  • tkn/template/infra-aws-ocp-snc.yaml
  • pkg/provider/aws/data/compute-request.go
  • cmd/mapt/cmd/params/params.go

Comment on lines +58 to +79
// TestFilterByFamily_CapAppliedAfterFilter verifies that when ComputeFamilies
// is set, matching types beyond MaxResults are still reachable by filterByFamily
// (i.e. the cap is applied after filtering, not before). This guards the fix for
// the bug where FilterVerbose capped results before filterByFamily ran, silently
// dropping allowlisted families ranked outside the top MaxResults.
func TestFilterByFamily_CapAppliedAfterFilter(t *testing.T) {
// Build 25 types: 5 non-matching (d3en) followed by 20 m6i types.
// If cap were applied before filter, the 5 d3en types would consume cap slots
// and only 15 m6i types would survive. With cap-after-filter all 20 survive.
var types []string
for i := 0; i < 5; i++ {
types = append(types, "d3en.12xlarge")
}
for i := 0; i < 20; i++ {
types = append(types, "m6i.xlarge")
}

got := filterByFamily(types, []string{"m6i"})
if len(got) != 20 {
t.Errorf("got %d results, want 20 — cap must be applied after filter, not before", len(got))
}
}

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

Make the cap-order regression test exercise the production path.

TestFilterByFamily_CapAppliedAfterFilter calls only filterByFamily. That helper does not apply computerequest.MaxResults, so the test passes even if getInstanceTypes truncates results before filtering.

Test the filter-and-cap composition, or invoke getInstanceTypes with a stubbed selector. Assert that the allowlisted values beyond the cap remain in the result.

🤖 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 `@pkg/provider/aws/data/compute-request_test.go` around lines 58 - 79, Update
TestFilterByFamily_CapAppliedAfterFilter to exercise the production
filter-and-cap path through getInstanceTypes, using a stubbed selector or
equivalent test setup. Configure computerequest.MaxResults and assert that
matching m6i values beyond the cap remain available, rather than testing
filterByFamily directly.

Comment on lines +268 to +270
if [[ "$(params.compute-families)" != "" ]]; then
cmd+="--compute-families '$(params.compute-families)' "
fi

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🔒 Security & Privacy | 🔴 Critical | ⚡ Quick win

Remove the shared eval-based command construction.

The new compute-families value is raw shell input. A permitted TaskRun or PipelineRun author can trigger command substitution or quote breaking, and the task exposes AWS credentials. Pass the value as data in an argument vector and validate family tokens before execution.

  • tkn/infra-aws-ocp-snc.yaml#L268-L270: pass compute-families as a separate argument without adding it to an evaluated command string.
  • tkn/infra-aws-rhel.yaml#L283-L285: apply the same safe argument handling in the generated RHEL task.
  • tkn/template/infra-aws-rhel.yaml#L283-L285: apply the same safe argument handling in the RHEL source template.

As per path instructions, focus on major issues impacting performance, readability, maintainability and security; avoid nitpicks and verbosity.

📍 Affects 3 files
  • tkn/infra-aws-ocp-snc.yaml#L268-L270 (this comment)
  • tkn/infra-aws-rhel.yaml#L283-L285
  • tkn/template/infra-aws-rhel.yaml#L283-L285
🤖 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 `@tkn/infra-aws-ocp-snc.yaml` around lines 268 - 270, Replace shared eval-based
command construction at tkn/infra-aws-ocp-snc.yaml lines 268-270,
tkn/infra-aws-rhel.yaml lines 283-285, and tkn/template/infra-aws-rhel.yaml
lines 283-285 with argument-vector handling: pass compute-families as a separate
data argument, validate each family token before execution, and preserve
omission when the value is empty. Apply the same change consistently in all
three files.

Source: Path instructions

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug] Expensive, specialised instances are selected when cpu/memory parameters are used

3 participants