ezdazuzena
ezdazuzena

Reputation: 6770

How list and filter stacks with boto3 cloudformation resource?

I want to get a list of stacks based on a give set of states. I am aware of a solution using the boto3 client for cloudformation, e.g. from the documentation:

response = client.list_stacks(
    NextToken='string',
    StackStatusFilter=[
        'CREATE_IN_PROGRESS'|'CREATE_FAILED'|'CREATE_COMPLETE'|
        'ROLLBACK_IN_PROGRESS'|'ROLLBACK_FAILED'|'ROLLBACK_COMPLETE'|
        'DELETE_IN_PROGRESS'|'DELETE_FAILED'|'DELETE_COMPLETE'|
        'UPDATE_IN_PROGRESS'|'UPDATE_COMPLETE_CLEANUP_IN_PROGRESS'|
        'UPDATE_COMPLETE'|'UPDATE_ROLLBACK_IN_PROGRESS'|'UPDATE_ROLLBACK_FAILED'|
        'UPDATE_ROLLBACK_COMPLETE_CLEANUP_IN_PROGRESS'|'UPDATE_ROLLBACK_COMPLETE'|
        'REVIEW_IN_PROGRESS',
    ]
)

(side note: I think the | should be ,, but anyway)

However, I understand that the "recommended" way is using boto3 resources to access the AWS services. Unfortunately, the boto3 cloudformation resource has not method to list and filter stacks (see the documentation).

I would like to avoid looping over all stacks and check each retrieved stack object for its status.

The only way I found so far, is the work around by accessing the client of the resource, though it feels a bit hacky and there is no way to filter for instance on the stackname.

cf = boto3.Session().resource('cloudformation')
cf.meta.client.list_stacks(StackStatusFilter=['ROLLBACK_COMPLETE'])

Question: Any idea how I could get something like list_stacks(StackStatusFilter=..) for cf, which is a cloudformation.ServiceResource object that allows to filter on the status and the stackname?

Upvotes: 1

Views: 12914

Answers (2)

Rafiq
Rafiq

Reputation: 1642

This is an old post, but I thought this detailed answer would be helpful to others.

import boto3
COMMA = ','
GOOD_STATES = ('CREATE_COMPLETE,UPDATE_COMPLETE,UPDATE_ROLLBACK_COMPLETE').split(COMMA)
BUSY_STATES = ('CREATE_IN_PROGRESS,ROLLBACK_IN_PROGRESS,DELETE_IN_PROGRESS,UPDATE_IN_PROGRESS,UPDATE_COMPLETE_CLEANUP_IN_PROGRESS,UPDATE_ROLLBACK_IN_PROGRESS,UPDATE_ROLLBACK_COMPLETE_CLEANUP_IN_PROGRESS,REVIEW_IN_PROGRESS').split(COMMA)
BAD_STATES  = ('CREATE_FAILED,ROLLBACK_FAILED,DELETE_FAILED,UPDATE_ROLLBACK_FAILED,DELETE_COMPLETE,ROLLBACK_COMPLETE').split(COMMA)

cfn_rs = boto3.resource('cloudformation')

#use one of the following that serves your purpose

good_stacks = [stack for stack in cfn_rs.stacks.all() if stack.stack_status in GOOD_STATES]
good_stack_names = [stack.name for stack in cfn_rs.stacks.all() if stack.stack_status in GOOD_STATES]

busy_stacks = [stack for stack in cfn_rs.stacks.all() if stack.stack_status in BUSY_STATES]
busy_stack_names = [stack.name for stack in cfn_rs.stacks.all() if stack.stack_status in BUSY_STATES]

bad_stacks = [stack for stack in cfn_rs.stacks.all() if stack.stack_status in BAD_STATES]
bad_stack_names = [stack.name for stack in cfn_rs.stacks.all() if stack.stack_status in BAD_STATES]

my_stacks = [stack for stack in cfn_rs.stacks.all() if stack.stack_status not in BAD_STATES]
my_stack_names = [stack.name for stack in cfn_rs.stacks.all() if stack.stack_status not in BAD_STATES]

Please note the difference between the following two:

  • ROLLBACK_COMPLETE: Stack creation process started and rolled back after some resources were created due to some failures. Usually, you need to delete this stack before creating a stack with the same name.
  • UPDATE_ROLLBACK_COMPLETE: Update process started on an existing stack but rolled back after modifying some resources due to some failures.

Upvotes: -1

bimsapi
bimsapi

Reputation: 5065

Interesting; that's an unfortunate asymmetry in the boto API. That said, I would stick with the resource and use a list comprehension vs. going through the meta attribute:

statuses = ['ROLLBACK_COMPLETE', 'CREATE_COMPLETE', 'UPDATE_COMPLETE']
cfn = boto3.resource('cloudformation')
stacks = [stack for stack in cfn.stacks.all() if stack.stack_status in statuses]

By dropping back to the meta.client, you get a dict response rather than Resource objects. If that's ok, just use cloudformation client instead of the resource. The comprehension will return Stack resource objects instead of dicts

Ultimately, either works and it's a matter of preference; just avoid mixing paradigms if you can.

Upvotes: 3

Related Questions