Skip to content

test(localstack): add integration tests for create-investigation Lambda - #202

Open
tiwillia wants to merge 1 commit into
openshift-online:mainfrom
tiwillia:tiwillia/localstack-create-investigation-tests
Open

test(localstack): add integration tests for create-investigation Lambda#202
tiwillia wants to merge 1 commit into
openshift-online:mainfrom
tiwillia:tiwillia/localstack-create-investigation-tests

Conversation

@tiwillia

@tiwillia tiwillia commented Aug 12, 2026

Copy link
Copy Markdown
Collaborator

Summary

Add 6 LocalStack integration tests for the create-investigation Lambda handler, exercising AWS-facing logic (ECS, EFS, STS) end-to-end. These complement the existing unit tests that mock all AWS calls.

Tests

Non-slow (4 tests, @pytest.mark.integration)

Test What it validates
test_create_investigation_creates_efs_access_point EFS AP path, POSIX UID/GID 1000, tags via real EFS API
test_create_investigation_registers_task_definition Task def family pattern, EFS volume config, 5 baked env vars (CLUSTER_ID, INVESTIGATION_ID, OC_VERSION, TASK_TIMEOUT, S3_AUDIT_BUCKET)
test_skip_task_creates_access_point_only AP created, no task def or task launched
test_idempotent_access_point_reuse Tag-based AP lookup returns same ID on repeat invocation

Slow (2 tests, @pytest.mark.integration @pytest.mark.slow, require ECS_EXECUTOR != local)

Test What it validates
test_create_investigation_launches_ecs_task Full e2e: task tags, deadline arithmetic, startedBy format
test_duplicate_investigation_returns_409 startedBy-based duplicate detection via real ECS list_tasks API

Design decisions

  • Handler loading: Uses importlib with unique module names per call. The handler creates boto3 clients at module scope, so AWS_ENDPOINT_URL must be set before loading. Each test gets a fresh module instance.
  • OIDC bypass: validate_oidc_token is patched on the loaded module to return known-good claims. All other AWS interactions (ECS, EFS, STS) hit LocalStack directly.
  • invoke_handler helper: Deduplicates the load/patch/invoke/parse/cleanup pattern across all tests. Each test body is pure assertion logic.
  • Task def registration test: Calls register_investigation_task_definition() directly instead of through lambda_handler() to avoid run_task side effects in the local ECS executor.

Verification

  • All 4 non-slow tests pass against LocalStack Pro
  • Full fast suite (make test-localstack-fast): 43 passed, 3 skipped, 0 failures — no regressions

Summary by CodeRabbit

  • Tests
    • Added comprehensive integration coverage for creating investigations in local development environments.
    • Verified access-point creation and reuse, task configuration, optional task execution, timeout metadata, and duplicate-request handling.
    • Confirmed duplicate investigations return an appropriate conflict response.
    • Added cleanup and environment handling to support reliable ECS, EFS, and IAM test scenarios.

Add 6 integration tests that exercise the create-investigation Lambda
handler against LocalStack, validating AWS-facing logic (ECS, EFS, STS)
end-to-end. These complement existing unit tests that mock all AWS calls.

Non-slow tests (4):
- test_create_investigation_creates_efs_access_point: validates EFS AP
  path, POSIX user (UID/GID 1000), and tags via real EFS API
- test_create_investigation_registers_task_definition: validates task def
  family pattern, EFS volume config, and baked env vars (CLUSTER_ID,
  INVESTIGATION_ID, OC_VERSION, TASK_TIMEOUT, S3_AUDIT_BUCKET)
- test_skip_task_creates_access_point_only: validates skip_task creates
  AP but no task def or ECS task
- test_idempotent_access_point_reuse: validates tag-based AP lookup
  returns same AP ID on second invocation

Slow tests (2, require ECS_EXECUTOR != local):
- test_create_investigation_launches_ecs_task: full e2e including tag
  roundtrip, deadline arithmetic, and startedBy verification
- test_duplicate_investigation_returns_409: validates startedBy-based
  duplicate detection against real ECS list_tasks API

Handler loading strategy:
- Uses importlib with unique module names per call to handle module-level
  boto3 client creation
- Sets AWS_ENDPOINT_URL before loading so clients connect to LocalStack
- Patches validate_oidc_token to bypass Keycloak JWKS validation

Tests cut from original spec as redundant with unit tests:
- get_config (no AWS interaction, identical to unit test)
- custom OC version (subset of task def registration test)
- missing OIDC token / invalid cluster_id (input validation, no AWS)
- response shape (pure Python formatting)
- deadline tag arithmetic (merged into task launch test)
@openshift-ci

openshift-ci Bot commented Aug 12, 2026

Copy link
Copy Markdown

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by:
Once this PR has been reviewed and has the lgtm label, please assign clcollins for approval. For more information see the Code Review Process.

The full list of commands accepted by this bot can be found here.

Details Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@coderabbitai

coderabbitai Bot commented Aug 12, 2026

Copy link
Copy Markdown

Walkthrough

Added a LocalStack integration-test suite for the create-investigation Lambda handler. The suite covers resource creation, task configuration, task launch metadata, idempotent reuse, skip_task behavior, cleanup, and duplicate-investigation responses.

Changes

Create-investigation integration coverage

Layer / File(s) Summary
LocalStack handler and resource fixtures
tests/localstack/integration/test_create_investigation.py
Adds dynamic handler loading, environment setup, Lambda event construction, OIDC mocking, response parsing, resource cleanup, and ECS, IAM, and task-definition fixtures.
Resource and task configuration validation
tests/localstack/integration/test_create_investigation.py
Tests EFS access-point properties and reuse, task-definition registration, environment variables, and skip_task behavior.
ECS execution and duplicate validation
tests/localstack/integration/test_create_investigation.py
Adds conditional slow tests for ECS task launch metadata, deadline tags, deterministic startedBy values, readiness polling, and HTTP 409 duplicate-investigation responses.

Estimated code review effort: 4 (Complex) | ~45 minutes


Important

Pre-merge checks failed

Please resolve all errors before merging. Addressing warnings is optional.

❌ Failed checks (1 error)

Check name Status Explanation Resolution
No-Hardcoded-Secrets ❌ Error The added make_event function assigns the token-named parameter the string literal 'mock-oidc-token' at line 83, matching the check's explicit hardcoded-token condition. Remove the hardcoded token default and inject a non-secret test token through a fixture or test configuration.
✅ Passed checks (10 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely describes the added LocalStack integration tests for the create-investigation Lambda.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
No-Weak-Crypto ✅ Passed The added test file has no MD5, SHA1, DES, RC4, Blowfish, ECB, custom crypto, or secret comparison; the exercised handler uses pre-existing SHA-256.
Container-Privileges ✅ Passed The PR adds only a Python integration test. Its ECS fixture has no privileged, host namespace, SYS_ADMIN, or allowPrivilegeEscalation setting, and does not explicitly run as root.
No-Sensitive-Data-In-Logs ✅ Passed The new file declares a logger but adds no logger or print calls; its mock token, email, and test credentials are not written to logs.
No-Injection-Vectors ✅ Passed The PR adds only a Python integration-test file; searches found no SQL, shell=True, eval/exec, pickle.loads, unsafe YAML, os.system, or dangerouslySetInnerHTML usage.
Ai-Attribution ✅ Passed The PR commit and description contain no AI-tool mention or attribution trailer; pre-existing Claude Co-authored-by trailers are outside this PR.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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 `@tests/localstack/integration/test_create_investigation.py`:
- Around line 154-156: Update the fixture resource-name generation around
cluster_name and base_task_family to use a collision-resistant single
per-instance identifier, such as one UUID or time.time_ns() value, instead of
int(time.time()). Apply that shared identifier consistently to all related ECS
cluster, task-definition family, and IAM role names in the fixture.
- Around line 481-489: Update the task-readiness polling loop in the
duplicate-detection test to call pytest.fail instead of pytest.skip when the
task never reaches RUNNING, ensuring ECS startup failures fail the test rather
than being treated as an unavailable environment.
🪄 Autofix

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: Repository YAML (base), Central YAML (inherited)

Review profile: CHILL

Plan: Enterprise

Run ID: 6dff8e3e-ee83-49b3-9035-3f157891ac97

📥 Commits

Reviewing files that changed from the base of the PR and between b4ad4dc and 2443ab9.

📒 Files selected for processing (1)
  • tests/localstack/integration/test_create_investigation.py

Comment on lines +154 to +156
ts = int(time.time())
cluster_name = f'test-create-inv-{ts}'
base_task_family = f'rosa-boundary-base-{ts}'

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

Use collision-resistant fixture resource names.

int(time.time()) has one-second resolution. Concurrent or rapid test execution can create the same ECS cluster, task-definition family, and IAM role names. LocalStack can then return AlreadyExists and make the suite flaky. Use one UUID or time.time_ns() value for this fixture instance.

🤖 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 `@tests/localstack/integration/test_create_investigation.py` around lines 154 -
156, Update the fixture resource-name generation around cluster_name and
base_task_family to use a collision-resistant single per-instance identifier,
such as one UUID or time.time_ns() value, instead of int(time.time()). Apply
that shared identifier consistently to all related ECS cluster, task-definition
family, and IAM role names in the fixture.

Comment on lines +481 to +489
for _ in range(24): # 24 × 5s = 120s max
desc = ecs_client.describe_tasks(
cluster=handler_env['cluster_name'], tasks=[task_arn]
)
if desc['tasks'][0].get('lastStatus') == 'RUNNING':
break
time.sleep(5)
else:
pytest.skip("Task never reached RUNNING — cannot test duplicate detection")

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 | 🟠 Major | ⚡ Quick win

Fail when the task does not reach RUNNING.

After ECS_EXECUTOR != 'local' selects this test, a task that never starts means duplicate detection was not validated. pytest.skip() hides broken task configuration or ECS execution. Replace it with pytest.fail().

Proposed fix
     else:
-        pytest.skip("Task never reached RUNNING — cannot test duplicate detection")
+        pytest.fail("Task never reached RUNNING; duplicate detection was not tested")
📝 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
for _ in range(24): # 24 × 5s = 120s max
desc = ecs_client.describe_tasks(
cluster=handler_env['cluster_name'], tasks=[task_arn]
)
if desc['tasks'][0].get('lastStatus') == 'RUNNING':
break
time.sleep(5)
else:
pytest.skip("Task never reached RUNNING — cannot test duplicate detection")
for _ in range(24): # 24 × 5s = 120s max
desc = ecs_client.describe_tasks(
cluster=handler_env['cluster_name'], tasks=[task_arn]
)
if desc['tasks'][0].get('lastStatus') == 'RUNNING':
break
time.sleep(5)
else:
pytest.fail("Task never reached RUNNING; duplicate detection was not tested")
🧰 Tools
🪛 Ruff (0.16.1)

[warning] 481-481: Comment contains ambiguous × (MULTIPLICATION SIGN). Did you mean x (LATIN SMALL LETTER X)?

(RUF003)

🤖 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 `@tests/localstack/integration/test_create_investigation.py` around lines 481 -
489, Update the task-readiness polling loop in the duplicate-detection test to
call pytest.fail instead of pytest.skip when the task never reaches RUNNING,
ensuring ECS startup failures fail the test rather than being treated as an
unavailable environment.

@tiwillia

Copy link
Copy Markdown
Collaborator Author

/hold

Don't review yet - I'd like to spend more time reviewing this first, its almost entirely AI generated with some hand-holding.

@openshift-ci openshift-ci Bot added the do-not-merge/hold Indicates that a PR should not merge because someone has issued a /hold command. label Aug 12, 2026
@openshift-ci

openshift-ci Bot commented Aug 12, 2026

Copy link
Copy Markdown

@tiwillia: The following test failed, say /retest to rerun all failed tests or /retest-required to rerun all mandatory failed tests:

Test name Commit Details Required Rerun command
ci/prow/localstack-integration-tests 2443ab9 link true /test localstack-integration-tests

Full PR test history. Your PR dashboard.

Details

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes-sigs/prow repository. I understand the commands that are listed here.

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

Labels

do-not-merge/hold Indicates that a PR should not merge because someone has issued a /hold command.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant