When developing for AWS, there is a pattern that you use each time a response to a service may return a lot of data. You get back some of the data, together with a token that you can provide to get another round of data.
As an example, let's take the service that returns the list of events from a Cloudformation template deployment. Here is how you would do it using Python and boto3:
cf_client = boto3.client("cloudformation")
response = cf_client.describe_stack_events(StackName="mystack")
# do something with the response
while response.get("NextToken"):
response = cf_client.describe_stack_events(
StackName="mystack",
NextToken=response.get("NextToken")
)
# do again something with the response
However, there is one thing that I do not like with this pattern: code repeat. You call the service at two different parts of your code, with almost identical parameters. And you process the response in the same way, again in two places. If you have to fix something in this code, you have to remember to fix in both places.
The approach I use to have your code only once, is to take advantage of Python's capacity to pass parameters as a dictionary. Here is my approach to this pattern:
cf_client = boto3.client("cloudformation")
next_token = "FIRST TIME"
params = {"StackName": "mystack"}
while next_token:
response = cf_client.describe_stack_events(**params)
# do something with the response
next_token = response.get("NextToken")
params["NextToken"] = next_token
I store my parameter list in a dictionary, and I initialize the next token with something that is not empty. So the first time in the loop will always run. I can then call my service, without the token. After processing the response, I then read the next token and fill it in my parameter list. The second time round, it will call the service with my token.
Something funny happened when I started using this pattern into our production code. We tried using Bandit, which is a tool that analyze your code and looks for security issues. It would systematically flag my pattern with this error:
[B105:hardcoded_password_string] Possible hardcoded password: 'FIRST TIME'
Well, I have to slightly modify my pattern to avoid using the word token...