Add Pagination for Organizations:ListAccounts

This commit is contained in:
Brian Pandola 2022-03-19 16:12:05 -07:00 committed by Brian Pandola
parent 662b96693d
commit a90d8c801b
5 changed files with 47 additions and 5 deletions

View File

@ -20,6 +20,8 @@ from moto.organizations.exceptions import (
PolicyTypeNotEnabledException,
TargetNotFoundException,
)
from moto.utilities.paginator import paginate
from .utils import PAGINATION_MODEL
class FakeOrganization(BaseModel):
@ -495,8 +497,11 @@ class OrganizationsBackend(BaseBackend):
next_token = str(len(accounts_resp))
return dict(CreateAccountStatuses=accounts_resp, NextToken=next_token)
@paginate(pagination_model=PAGINATION_MODEL)
def list_accounts(self):
return dict(Accounts=[account.describe() for account in self.accounts])
accounts = [account.describe() for account in self.accounts]
accounts = sorted(accounts, key=lambda x: x["JoinedTimestamp"])
return accounts
def list_accounts_for_parent(self, **kwargs):
parent_id = self.validate_parent_id(kwargs["ParentId"])

View File

@ -85,7 +85,15 @@ class OrganizationsResponse(BaseResponse):
)
def list_accounts(self):
return json.dumps(self.organizations_backend.list_accounts())
max_results = self._get_int_param("MaxResults")
next_token = self._get_param("NextToken")
accounts, next_token = self.organizations_backend.list_accounts(
max_results=max_results, next_token=next_token
)
response = {"Accounts": accounts}
if next_token:
response["NextToken"] = next_token
return json.dumps(response)
def list_accounts_for_parent(self):
return json.dumps(

View File

@ -33,6 +33,16 @@ ACCOUNT_ID_REGEX = r"[0-9]{%s}" % ACCOUNT_ID_SIZE
CREATE_ACCOUNT_STATUS_ID_REGEX = r"car-[a-z0-9]{%s}" % CREATE_ACCOUNT_STATUS_ID_SIZE
POLICY_ID_REGEX = r"%s|p-[a-z0-9]{%s}" % (DEFAULT_POLICY_ID, POLICY_ID_SIZE)
PAGINATION_MODEL = {
"list_accounts": {
"input_token": "next_token",
"limit_key": "max_results",
"limit_default": 100,
"result_key": "Accounts",
"unique_attribute": "JoinedTimestamp",
},
}
def make_random_org_id():
# The regex pattern for an organization ID string requires "o-"

View File

@ -137,7 +137,7 @@ class Paginator(object):
predicate_values = unique_attributes.split("|")
for (index, attr) in enumerate(self._unique_attributes):
curr_val = item[attr] if type(item) == dict else getattr(item, attr, None)
if not curr_val == predicate_values[index]:
if not str(curr_val) == predicate_values[index]:
return False
return True
@ -148,9 +148,9 @@ class Paginator(object):
range_keys = []
for attr in self._unique_attributes:
if type(next_item) == dict:
range_keys.append(next_item[attr])
range_keys.append(str(next_item[attr]))
else:
range_keys.append(getattr(next_item, attr))
range_keys.append(str(getattr(next_item, attr)))
token_dict["uniqueAttributes"] = "|".join(range_keys)
return self._token_encoder.encode(token_dict)

View File

@ -229,6 +229,25 @@ def test_list_accounts():
accounts[3]["Email"].should.equal(mockname + "2" + "@" + mockdomain)
@mock_organizations
def test_list_accounts_pagination():
client = boto3.client("organizations", region_name="us-east-1")
client.create_organization(FeatureSet="ALL")
for i in range(25):
name = mockname + str(i)
email = name + "@" + mockdomain
client.create_account(AccountName=name, Email=email)
response = client.list_accounts()
response.should_not.have.key("NextToken")
len(response["Accounts"]).should.be.greater_than_or_equal_to(i)
paginator = client.get_paginator("list_accounts")
page_iterator = paginator.paginate(MaxResults=5)
for page in page_iterator:
len(page["Accounts"]).should.be.lower_than_or_equal_to(5)
page["Accounts"][-1]["Name"].should.contain("24")
@mock_organizations
def test_list_accounts_for_parent():
client = boto3.client("organizations", region_name="us-east-1")