1

I am using Django as the framework. I am using boto3 to create an AWS account in my views function. Every created aws account will have an AccountId. Before going into further details, here is my snippet :

 org = boto3.client('organizations')
 acc = org.create_account(
         Email=email,
         AccountName=lab_name,
         IamUserAccessToBilling='ALLOW'
         )
 cid = acc['CreateAccountStatus']['Id']
 time.sleep(70)

 #GET ACCOUNT DETAILS
 status = org.describe_create_account_status(
      CreateAccountRequestId=cid
     )
 accid = status['CreateAccountStatus']['AccountId']

Initially I am creating the account. Like I mentioned before it takes some time (around 1 to 1.5 mins) to create the account. Then I need to GET the account details, one of the details being the AccountId. I tried increasing the sleep time to resolve this issue but that didn't help. I am getting an error when I try to GET the AccountId value in 'accid' declaration line. The error I am getting is:

KeyError: AccountId doesn't exist

This is probably happening because the account is not getting created yet and before that event my code is trying to fetch the AccountId value. How can I get the AccountId value then ? Should I try putting it in a loop or using try and except block to avoid the error message ? Please help. Thanks in advance.

DYZ
  • 55,249
  • 10
  • 64
  • 93
Siddharth Singh
  • 105
  • 3
  • 15

2 Answers2

1
 status = org.describe_create_account_status(CreateAccountRequestId=cid)

 while status.get('CreateAccountStatus',{}).get('AccountId',None) is None:
     # sleep here
     status = org.describe_create_account_status(CreateAccountRequestId=cid)

 accid = status['CreateAccountStatus']['AccountId']

This will use the .get(key, default) of dict to supply it (or an empty dict) for 'CreateAccountStatus' and a None for 'AccountId' and loop while it is None.

About dict.get() and the dict.get-API


As pointed out by JonClements it might be more pythonic to use a while True: ... break ... construct for this:

while True:
    status = org.describe_create_account_status(CreateAccountRequestId=cid)
    try:
        accid = status['CreateAccountStatus']['AccountId']
        break
    except KeyError:
        time.sleep(30)

This avoids duplication of the status = ... line and makes for a more clearer flow.

Using try: ... except: fits better with the pythonic ask-forgiveness-not-permission approach.

Patrick Artner
  • 50,409
  • 9
  • 43
  • 69
  • It's arguably better to make this a `while True` loop and moving the checking condition so it only appears once, and when it's met, then `break` from the loop... That way - you avoid the possibility of forgetting to update both of the `status = `... I'd probably go for something like: https://gist.github.com/anonymous/a55306abe3d26dcfc51020f0532595c6 though – Jon Clements Feb 16 '18 at 08:49
  • Feel free to extend yours if you're happy to do so and explain it :) – Jon Clements Feb 16 '18 at 09:05
  • @PatrickArtner Hi I tried your method.. No error is being thrown but the code kind of stuck / froze. Nothing is moving forward. I gave sleep time as 60. – Siddharth Singh Feb 16 '18 at 10:00
  • @JonClements integrated it. – Patrick Artner Feb 16 '18 at 10:07
  • @SiddharthSingh - put a `print('.', end ="")` statement inside to verify it is looping - a sleep of 60 will freeze it for 60s, may be better to reduce to 5 and output something so you do not get itchy with non-responsiveness. Do you have a second way to verify if the account is being created (Webinterface etc?) so you can check that while waiting? – Patrick Artner Feb 16 '18 at 10:12
  • Yes.. The webpage will refresh after the account is created and list its details... Okay I will reduce the sleep time and check – Siddharth Singh Feb 16 '18 at 10:16
  • Yes it's printing.. it is looping then – Siddharth Singh Feb 16 '18 at 10:22
  • But it keeps on printing.. It doesn't come out of the loop – Siddharth Singh Feb 16 '18 at 10:30
  • I got out of the loop but the keyerror persists.. Should I increase the sleep time then ? – Siddharth Singh Feb 16 '18 at 10:34
  • @SiddharthSingh If it gets out of the loop, the key should be in there. check if the ID that you stored inside `CID` is the same as on your webinterface. If it leaves the loop (both versions) it should have your accountID inside `accid`. Use a debugger and set breakpoints to debug it – Patrick Artner Feb 16 '18 at 10:38
0

In your acc['CreateAccountStatus'] variable, you should have a key State that will tell you when the creation is completed.

Here is the documentation, see in the Response Syntax

DFE
  • 126
  • 9
  • 1
    _CreateAccountStatus (dict) -- A structure that contains details about the request to create an account. This response structure might not be fully populated when you first receive it because account creation is an asynchronous process. You can pass the returned CreateAccountStatus ID as a parameter to `` DescribeCreateAccountStatus `` to get status about the progress of the request at later times._ - it is async and won't update itself w/o pulling – Patrick Artner Feb 16 '18 at 08:34
  • Thanks for the reply pal :) I am trying this method. Read the documentation. I am trying to use if control statement saying if the CreateAccountStatus State is 'SUCCEEDED' only then proceed with the next steps. – Siddharth Singh Feb 16 '18 at 08:36