Skip to content

feat: add policy client and tests#427

Open
nborges-aws wants to merge 3 commits intomainfrom
policyClient
Open

feat: add policy client and tests#427
nborges-aws wants to merge 3 commits intomainfrom
policyClient

Conversation

@nborges-aws
Copy link
Copy Markdown
Contributor

Issue #, if available: Issue #392

Description of changes:

  • Add PolicyEngineClient with__getattr__passthrough
  • Control plane allowlisted methods (14):
    • Policy engine CRUD: create_policy_engine, get_policy_engine, list_policy_engines, update_policy_engine, delete_policy_engine
    • Policy CRUD: create_policy, get_policy, list_policies, update_policy, delete_policy
    • Policy generation: start_policy_generation, get_policy_generation, list_policy_generations, list_policy_generation_assets
  • Add *_and_wait polling methods using shared wait_until/wait_until_deleted utilities:
    • create_policy_engine_and_wait, update_policy_engine_and_wait, delete_policy_engine_and_wait
    • create_policy_and_wait, delete_policy_and_wait
  • Add higher-level orchestration methods:
    • generate_policy_asset_and_wait — starts NL→Cedar generation, polls until complete, optionally fetches generated assets
    • generate_and_create_policy — end-to-end flow: generate asset + create policy from it in one call
    • create_policy_from_generation_asset — creates a policy from a specific generation asset
    • create_or_get_policy_engine / create_or_get_policy — idempotent creates (handles ConflictException by finding existing resource)
  • All *_and_wait methods accept WaitConfig for configurable polling behavior and apply convert_kwargs for snake_case support

Test plan:

  • Integration tests (10 total):
    • Full CRUD lifecycle: create engine → get (camelCase + snake_case) → update → create policy → get policy → list engines → list policies → delete policy → delete engine
    • Validates passthrough, snake_case conversion, *_and_wait polling, and cleanup
  • Unit tests (30 total, all passing):
    • Init: region, region fallback, boto3 client creation, integration_source
    • Passthrough: CP forwarding, snake_case conversion, AttributeError on unknown method, allowlist contents
    • Generate policy: immediate success, fetch assets, polling, failure, timeout
    • Create from generation asset: definition shape, optional params
    • Wait methods: immediate active, polling, failed status, timeout (engine + policy)
    • Idempotent creates: new resource, conflict → find existing, not found → reraise, non-conflict error → reraise

By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the terms of your choice.

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented Apr 23, 2026

✅ No Breaking Changes Detected

No public API breaking changes found in this PR.

Copy link
Copy Markdown
Contributor

@Hweinstock Hweinstock left a comment

Choose a reason for hiding this comment

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

Nice! I like the client. Few questions on the integ tests, but otherwise looks good.

)
except Exception as e:
print(f"Failed to delete policy {policy_id}: {e}")
# Wait for policy deletes to complete before deleting engines
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.

should we poll here instead of waiting?

Copy link
Copy Markdown
Contributor Author

@nborges-aws nborges-aws Apr 24, 2026

Choose a reason for hiding this comment

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

Yep. I added the short delay just as a safeguard, but delete_and_wait method is more robust. I'll change to use that

policyEngineId=self.engine_ids[0],
description={"optionalValue": "updated by integ test"},
)
assert updated["status"] == "ACTIVE"
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.

should we verify that the policy actually updated?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Definitely. I'll assert against the description

cls.policy_ids = []
sts = boto3.client("sts", region_name=cls.region)
account_id = sts.get_caller_identity()["Account"]
cls.gateway_resource_arn = f"arn:aws:bedrock-agentcore:{cls.region}:{account_id}:gateway/*"
Copy link
Copy Markdown
Contributor

@Hweinstock Hweinstock Apr 23, 2026

Choose a reason for hiding this comment

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

is this used anywhere?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Good catch. I previously needed this in the cedar statement for one of the tests, but found a way around it. Leftover artifact that can be removed.

Comment thread src/bedrock_agentcore/policy/client.py Outdated
logger.info("Policy engine '%s' already exists, looking up...", name)
engine_id = self._find_policy_engine_by_name(name)
if not engine_id:
raise
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.

nit: if a gateway exists, but the lookup fails, the user sees a conflict exception here. Not sure how this could happen, but we might want a better error to avoid confusing customers.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Will update error messaging here



@pytest.mark.integration
class TestPolicyEngineClient:
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.

should we also test create_or_get methods?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Yep, I'll add these

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.

2 participants