Skip to content

Commit b48f761

Browse files
author
Mohamed Zeidan
committed
2 integ happycase tests
1 parent 3a87ee8 commit b48f761

File tree

2 files changed

+11
-270
lines changed

2 files changed

+11
-270
lines changed
Lines changed: 7 additions & 123 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,19 @@
11
"""
22
Integration tests for CLI cluster stack deletion functionality.
33
4-
Tests the complete user workflow for deleting cluster stacks via CLI commands.
5-
Uses CLI commands as a user would, focusing on deletion process and error handling.
4+
Tests the basic happy path user workflow for deleting cluster stacks via CLI commands.
5+
Focuses on core functionality with minimal stack creation/deletion overhead.
6+
7+
Detailed error handling and edge cases are covered by unit tests.
68
"""
79
import time
810
import pytest
911
import boto3
10-
from unittest.mock import patch, MagicMock
1112
from click.testing import CliRunner
1213

1314
from sagemaker.hyperpod.cli.commands.cluster_stack import delete_cluster_stack
1415
from test.integration_tests.cluster_management.utils import (
1516
assert_command_succeeded,
16-
assert_command_failed_with_helpful_error,
1717
assert_yes_no_prompt_displayed,
1818
assert_success_message_displayed,
1919
)
@@ -30,13 +30,6 @@ def runner():
3030
return CliRunner()
3131

3232

33-
@pytest.fixture(scope="module")
34-
def test_stack_name():
35-
"""Generate a unique test stack name."""
36-
import uuid
37-
return f"{TEST_STACK_PREFIX}-{str(uuid.uuid4())[:8]}"
38-
39-
4033
@pytest.fixture(scope="module")
4134
def cfn_client():
4235
"""CloudFormation client for test infrastructure."""
@@ -96,69 +89,11 @@ def wait_for_stack_delete_complete(cfn_client, stack_name, timeout_minutes=10):
9689

9790
# --------- CLI Delete Tests ---------
9891

99-
@pytest.mark.dependency(name="test_delete_nonexistent_stack")
100-
def test_delete_nonexistent_stack_error_handling(runner):
101-
"""Test CLI error handling when trying to delete a non-existent stack."""
102-
nonexistent_stack = "nonexistent-stack-12345"
103-
104-
result = runner.invoke(delete_cluster_stack, [
105-
nonexistent_stack,
106-
"--region", REGION
107-
], input='y\n', catch_exceptions=False)
108-
109-
# CLI shows user-friendly error message but doesn't fail with non-zero exit code
110-
assert "not found" in result.output.lower()
111-
assert nonexistent_stack in result.output
112-
113-
114-
@pytest.mark.dependency(name="test_delete_with_confirmation_prompt")
115-
def test_delete_with_confirmation_prompt(runner, test_stack_name, cfn_client):
116-
"""Test CLI deletion with user confirmation prompt."""
117-
# Create test stack
118-
create_test_stack(cfn_client, test_stack_name)
119-
120-
# Test deletion with confirmation prompt (simulate 'n' response)
121-
result = runner.invoke(delete_cluster_stack, [
122-
test_stack_name,
123-
"--region", REGION
124-
], input='n\n', catch_exceptions=False)
125-
126-
# Should show confirmation prompt and abort on 'n'
127-
assert_yes_no_prompt_displayed(result)
128-
assert "Aborted" in result.output or "cancelled" in result.output.lower()
129-
130-
# Verify stack still exists
131-
response = cfn_client.describe_stacks(StackName=test_stack_name)
132-
assert len(response['Stacks']) == 1
133-
assert response['Stacks'][0]['StackStatus'] != 'DELETE_COMPLETE'
134-
135-
136-
@pytest.mark.dependency(name="test_delete_with_user_confirmation_yes", depends=["test_delete_with_confirmation_prompt"])
137-
def test_delete_with_user_confirmation_yes(runner, test_stack_name, cfn_client):
138-
"""Test CLI deletion with user confirmation (yes response)."""
139-
result = runner.invoke(delete_cluster_stack, [
140-
test_stack_name,
141-
"--region", REGION
142-
], input='y\n', catch_exceptions=False)
143-
144-
assert_command_succeeded(result)
145-
assert_success_message_displayed(result, ["deletion", "initiated"])
146-
147-
# Wait for deletion to complete
148-
wait_for_stack_delete_complete(cfn_client, test_stack_name)
149-
150-
# Verify stack is deleted
151-
with pytest.raises(Exception) as exc_info:
152-
cfn_client.describe_stacks(StackName=test_stack_name)
153-
assert "does not exist" in str(exc_info.value)
154-
155-
156-
@pytest.mark.dependency(name="test_delete_with_user_confirmation")
15792
def test_delete_with_user_confirmation(runner, cfn_client):
158-
"""Test CLI deletion with user confirmation (yes response)."""
159-
# Create a new test stack for this test
93+
"""Test CLI deletion happy path with user confirmation."""
94+
# Create a test stack for this test
16095
import uuid
161-
stack_name = f"{TEST_STACK_PREFIX}-confirm-{str(uuid.uuid4())[:8]}"
96+
stack_name = f"{TEST_STACK_PREFIX}-happy-{str(uuid.uuid4())[:8]}"
16297
create_test_stack(cfn_client, stack_name)
16398

16499
try:
@@ -187,54 +122,3 @@ def test_delete_with_user_confirmation(runner, cfn_client):
187122
except:
188123
pass
189124
raise
190-
191-
192-
@pytest.mark.dependency(name="test_retain_resources_validation")
193-
def test_retain_resources_validation_error(runner, cfn_client):
194-
"""Test CLI validation of retain-resources parameter on non-DELETE_FAILED stack."""
195-
# Create a test stack in CREATE_COMPLETE state
196-
import uuid
197-
stack_name = f"{TEST_STACK_PREFIX}-retain-{str(uuid.uuid4())[:8]}"
198-
create_test_stack(cfn_client, stack_name)
199-
200-
try:
201-
# Try to delete with retain-resources (should fail validation)
202-
result = runner.invoke(delete_cluster_stack, [
203-
stack_name,
204-
"--region", REGION,
205-
"--retain-resources", "TestBucket"
206-
], input='y\n', catch_exceptions=False)
207-
208-
# Should fail with helpful error about retain-resources limitation
209-
assert result.exit_code != 0
210-
assert "retain" in result.output.lower()
211-
assert "only works on failed deletions" in result.output or "DELETE_FAILED" in result.output
212-
213-
# Verify stack still exists (deletion should not have been attempted)
214-
response = cfn_client.describe_stacks(StackName=stack_name)
215-
assert len(response['Stacks']) == 1
216-
assert response['Stacks'][0]['StackStatus'] == 'CREATE_COMPLETE'
217-
218-
finally:
219-
# Cleanup
220-
try:
221-
cfn_client.delete_stack(StackName=stack_name)
222-
wait_for_stack_delete_complete(cfn_client, stack_name)
223-
except:
224-
pass
225-
226-
227-
@pytest.mark.dependency(name="test_region_parameter")
228-
def test_region_parameter_handling(runner):
229-
"""Test CLI handling of region parameter."""
230-
nonexistent_stack = "test-stack-region-param"
231-
232-
# Test with explicit region
233-
result = runner.invoke(delete_cluster_stack, [
234-
nonexistent_stack,
235-
"--region", "us-west-1"
236-
], input='y\n', catch_exceptions=False)
237-
238-
# CLI shows user-friendly error message for non-existent stack
239-
assert "not found" in result.output.lower() or "does not exist" in result.output.lower()
240-
assert nonexistent_stack in result.output
Lines changed: 4 additions & 147 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,15 @@
11
"""
22
Integration tests for SDK cluster stack deletion functionality.
33
4-
Tests the HpClusterStack.delete() method and related SDK functionality.
5-
Focuses on programmatic usage patterns and error handling.
4+
Tests the basic happy path for HpClusterStack.delete() method.
5+
Focuses on core SDK functionality with minimal stack creation/deletion overhead.
6+
7+
Detailed error handling and edge cases are covered by unit tests.
68
"""
79
import time
810
import pytest
911
import boto3
1012
import uuid
11-
from unittest.mock import patch, MagicMock
1213

1314
from sagemaker.hyperpod.cluster_management.hp_cluster_stack import HpClusterStack
1415

@@ -35,14 +36,6 @@ def create_test_stack(cfn_client, stack_name):
3536
"Properties": {
3637
"BucketName": f"{stack_name.lower()}-sdk-test-bucket"
3738
}
38-
},
39-
"TestParameter": {
40-
"Type": "AWS::SSM::Parameter",
41-
"Properties": {
42-
"Name": f"/test/{stack_name}/parameter",
43-
"Type": "String",
44-
"Value": "test-value"
45-
}
4639
}
4740
},
4841
"Outputs": {
@@ -85,24 +78,6 @@ def wait_for_stack_delete_complete(cfn_client, stack_name, timeout_minutes=10):
8578

8679
# --------- SDK Delete Tests ---------
8780

88-
@pytest.mark.dependency(name="test_sdk_delete_nonexistent_stack")
89-
def test_sdk_delete_nonexistent_stack_error_handling():
90-
"""Test SDK error handling when trying to delete a non-existent stack."""
91-
nonexistent_stack = f"nonexistent-stack-{str(uuid.uuid4())[:8]}"
92-
93-
# Should raise ValueError with helpful message
94-
with pytest.raises(ValueError) as exc_info:
95-
HpClusterStack.delete(
96-
stack_name=nonexistent_stack,
97-
region=REGION
98-
)
99-
100-
error_message = str(exc_info.value).lower()
101-
assert "not found" in error_message or "does not exist" in error_message
102-
assert nonexistent_stack in str(exc_info.value)
103-
104-
105-
@pytest.mark.dependency(name="test_sdk_delete_basic_functionality")
10681
def test_sdk_delete_basic_functionality(cfn_client):
10782
"""Test basic SDK deletion functionality with auto-confirmation."""
10883
# Create test stack
@@ -131,121 +106,3 @@ def test_sdk_delete_basic_functionality(cfn_client):
131106
except:
132107
pass
133108
raise
134-
135-
136-
@pytest.mark.dependency(name="test_sdk_delete_with_region_parameter")
137-
def test_sdk_delete_with_region_parameter(cfn_client):
138-
"""Test SDK deletion with explicit region parameter."""
139-
# Create test stack
140-
stack_name = f"{TEST_STACK_PREFIX}-region-{str(uuid.uuid4())[:8]}"
141-
create_test_stack(cfn_client, stack_name)
142-
143-
try:
144-
# Delete using SDK with explicit region
145-
HpClusterStack.delete(
146-
stack_name=stack_name,
147-
region=REGION
148-
)
149-
150-
# Wait for deletion to complete
151-
wait_for_stack_delete_complete(cfn_client, stack_name)
152-
153-
# Verify stack is deleted
154-
with pytest.raises(Exception) as exc_info:
155-
cfn_client.describe_stacks(StackName=stack_name)
156-
assert "does not exist" in str(exc_info.value)
157-
158-
except Exception:
159-
# Cleanup in case of test failure
160-
try:
161-
cfn_client.delete_stack(StackName=stack_name)
162-
except:
163-
pass
164-
raise
165-
166-
167-
@pytest.mark.dependency(name="test_sdk_retain_resources_validation")
168-
def test_sdk_retain_resources_validation_error(cfn_client):
169-
"""Test SDK validation of retain_resources parameter on non-DELETE_FAILED stack."""
170-
# Create test stack in CREATE_COMPLETE state
171-
stack_name = f"{TEST_STACK_PREFIX}-retain-{str(uuid.uuid4())[:8]}"
172-
create_test_stack(cfn_client, stack_name)
173-
174-
try:
175-
# Try to delete with retain_resources (should raise ValueError)
176-
with pytest.raises(ValueError) as exc_info:
177-
HpClusterStack.delete(
178-
stack_name=stack_name,
179-
region=REGION,
180-
retain_resources=["TestBucket"]
181-
)
182-
183-
# Should have helpful error about retain_resources limitation
184-
error_message = str(exc_info.value).lower()
185-
assert "retain" in error_message
186-
assert "delete_failed" in error_message
187-
assert "can only be used" in error_message or "only supported" in error_message or "only works" in error_message
188-
189-
# Verify stack still exists (deletion should not have been attempted)
190-
response = cfn_client.describe_stacks(StackName=stack_name)
191-
assert len(response['Stacks']) == 1
192-
assert response['Stacks'][0]['StackStatus'] == 'CREATE_COMPLETE'
193-
194-
finally:
195-
# Cleanup
196-
try:
197-
cfn_client.delete_stack(StackName=stack_name)
198-
wait_for_stack_delete_complete(cfn_client, stack_name)
199-
except:
200-
pass
201-
202-
203-
@pytest.mark.dependency(name="test_sdk_delete_with_logging")
204-
def test_sdk_delete_with_custom_logger(cfn_client):
205-
"""Test SDK deletion with custom logger parameter."""
206-
import logging
207-
from io import StringIO
208-
209-
# Create test stack
210-
stack_name = f"{TEST_STACK_PREFIX}-logger-{str(uuid.uuid4())[:8]}"
211-
create_test_stack(cfn_client, stack_name)
212-
213-
# Set up custom logger to capture log messages
214-
log_stream = StringIO()
215-
logger = logging.getLogger(f"test_logger_{uuid.uuid4().hex[:8]}")
216-
logger.setLevel(logging.INFO)
217-
handler = logging.StreamHandler(log_stream)
218-
handler.setFormatter(logging.Formatter('%(levelname)s: %(message)s'))
219-
logger.addHandler(handler)
220-
221-
try:
222-
# Delete using SDK with custom logger
223-
HpClusterStack.delete(
224-
stack_name=stack_name,
225-
region=REGION,
226-
logger=logger
227-
)
228-
229-
# Check that logger captured relevant messages
230-
log_output = log_stream.getvalue()
231-
assert "auto-confirming" in log_output.lower() or "deletion" in log_output.lower()
232-
233-
# Wait for deletion to complete
234-
wait_for_stack_delete_complete(cfn_client, stack_name)
235-
236-
# Verify stack is deleted
237-
with pytest.raises(Exception) as exc_info:
238-
cfn_client.describe_stacks(StackName=stack_name)
239-
assert "does not exist" in str(exc_info.value)
240-
241-
except Exception:
242-
# Cleanup in case of test failure
243-
try:
244-
cfn_client.delete_stack(StackName=stack_name)
245-
except:
246-
pass
247-
raise
248-
finally:
249-
# Clean up logger
250-
logger.removeHandler(handler)
251-
handler.close()

0 commit comments

Comments
 (0)