{"action":"created","comment":{"url":"https://api.github.com/repos/boto/botocore/pulls/comments/51389024","id":51389024,"diff_hunk":"@@ -0,0 +1,197 @@\n+{\n+    \"version\": 2,\n+    \"waiters\": {\n+        \"StackAvailable\": {\n+            \"delay\": 30,","path":"botocore/data/cloudformation/2010-05-15/waiters-2.json","position":5,"original_position":5,"commit_id":"e4e76f73a4ce1a4183c6aeba969be84841c74fc2","original_commit_id":"e4e76f73a4ce1a4183c6aeba969be84841c74fc2","user":{"login":"quiver","id":266641,"avatar_url":"https://avatars.githubusercontent.com/u/266641?v=3","gravatar_id":"","url":"https://api.github.com/users/quiver","html_url":"https://github.com/quiver","followers_url":"https://api.github.com/users/quiver/followers","following_url":"https://api.github.com/users/quiver/following{/other_user}","gists_url":"https://api.github.com/users/quiver/gists{/gist_id}","starred_url":"https://api.github.com/users/quiver/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/quiver/subscriptions","organizations_url":"https://api.github.com/users/quiver/orgs","repos_url":"https://api.github.com/users/quiver/repos","events_url":"https://api.github.com/users/quiver/events{/privacy}","received_events_url":"https://api.github.com/users/quiver/received_events","type":"User","site_admin":false},"body":"> What informs the 30 value you picked here?\r\n\r\nMost Cloudformation APIs take many minutes to complete. For long-polling, 15 seconds are too frequent, 60 seconds are too long(FYW, Cloudfront and Redshift use 60 secs as polling intervals), and I thought 30 seconds are a good compromise.","created_at":"2016-02-01T08:12:50Z","updated_at":"2016-02-01T08:12:50Z","html_url":"https://github.com/boto/botocore/pull/630#discussion_r51389024","pull_request_url":"https://api.github.com/repos/boto/botocore/pulls/630","_links":{"self":{"href":"https://api.github.com/repos/boto/botocore/pulls/comments/51389024"},"html":{"href":"https://github.com/boto/botocore/pull/630#discussion_r51389024"},"pull_request":{"href":"https://api.github.com/repos/boto/botocore/pulls/630"}}},"pull_request":{"url":"https://api.github.com/repos/boto/botocore/pulls/630","id":42604492,"html_url":"https://github.com/boto/botocore/pull/630","diff_url":"https://github.com/boto/botocore/pull/630.diff","patch_url":"https://github.com/boto/botocore/pull/630.patch","issue_url":"https://api.github.com/repos/boto/botocore/issues/630","number":630,"state":"open","locked":false,"title":"Implement CloudFormation waiters","user":{"login":"quiver","id":266641,"avatar_url":"https://avatars.githubusercontent.com/u/266641?v=3","gravatar_id":"","url":"https://api.github.com/users/quiver","html_url":"https://github.com/quiver","followers_url":"https://api.github.com/users/quiver/followers","following_url":"https://api.github.com/users/quiver/following{/other_user}","gists_url":"https://api.github.com/users/quiver/gists{/gist_id}","starred_url":"https://api.github.com/users/quiver/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/quiver/subscriptions","organizations_url":"https://api.github.com/users/quiver/orgs","repos_url":"https://api.github.com/users/quiver/repos","events_url":"https://api.github.com/users/quiver/events{/privacy}","received_events_url":"https://api.github.com/users/quiver/received_events","type":"User","site_admin":false},"body":"# Cloudformation Waiters\r\n\r\nTwo sub-commands are added with this PR\r\n\r\n## wait stack-available\r\n\r\nto be used with `create-stack`/`update-stack`\r\n\r\n    $ aws cloudformation create-stack --stack-name foo --template-body file://foo.template.json\r\n    $ aws cloudformation wait stack-available --stack-name foo\r\n\r\no success status\r\n\r\n* CREATE_COMPLETE\r\n* UPDATE_COMPLETE\r\n\r\no retry status\r\n\r\n* CREATE_IN_PROGRESS\r\n* UPDATE_IN_PROGRESS\r\n* UPDATE_COMPLETE_CLEANUP_IN_PROGRESS\r\n\r\no failure status\r\n\r\n* other statuses\r\n\r\n## wait stack-deleted\r\n\r\nto be used with `delete-stack`\r\n\r\n    $ aws cloudformation delete-stack --stack-name foo\r\n    $ aws cloudformation wait stack-deleted --stack-name foo\r\n\r\no success status\r\n\r\n* DELETE_COMPLETE (when queried with stack-id)\r\n* ValidationError (when queried with stack-name)\r\n\r\no retry status\r\n\r\n* DELETE_IN_PROGRESS\r\n\r\no failure status\r\n\r\n* other statuses\r\n\r\n\r\n## retry handling\r\n\r\nPoll every 30 seconds for 120 times(60 minutes) with `describe-stacks` API and query the response with `Stacks[].StackStatus`.\r\n\r\nWhen provisioning services like cloudformation or DB(RDS, RedShift, etc) or Elastic BeanStalk or changing magnetic device to SSD,  CFn takes a long time, so I set threshold times(60 mins) longer than other wait commands.\r\n\r\n# StackStatus\r\n\r\n## List of StackStatus\r\n\r\nhttp://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/using-cfn-describing-stacks.html\r\n\r\n* CREATE_COMPLETE\r\n* CREATE_IN_PROGRESS\r\n* CREATE_FAILED\r\n* DELETE_COMPLETE\r\n* DELETE_FAILED\r\n* DELETE_IN_PROGRESS\r\n* ROLLBACK_COMPLETE\r\n* ROLLBACK_FAILED\r\n* ROLLBACK_IN_PROGRESS\r\n* UPDATE_COMPLETE\r\n* UPDATE_COMPLETE_CLEANUP_IN_PROGRESS\r\n* UPDATE_IN_PROGRESS\r\n* UPDATE_ROLLBACK_COMPLETE\r\n* UPDATE_ROLLBACK_COMPLETE_CLEANUP_IN_PROGRESS\r\n* UPDATE_ROLLBACK_FAILED\r\n* UPDATE_ROLLBACK_IN_PROGRESS\r\n\r\n## StackStatus state diagram\r\n\r\nBased on the document and playing with CFn and advices from my colleagues, I created a StackStatus state diagram.\r\nThis diagram does *not* cover every single flow, but will cover most of the state changes(I think).\r\n\r\n* Blue-filled statuses are success\r\n* Green-filled statuses are retry\r\n* Other statuses are failure\r\n\r\n### create-stack \r\n\r\n![create-stack](https://cloud.githubusercontent.com/assets/266641/9308707/804b53e2-4540-11e5-9b95-0b14c9e43254.png)\r\n\r\n* If you pass `--disable-rollback`, rollback won't occur.\r\n* `CREATE_IN_PROGRESS` stack can be deleted with `DeleteStack` API\r\n\r\n### update-stack\r\n\r\n![update-stack](https://cloud.githubusercontent.com/assets/266641/9308712/856fc308-4540-11e5-9656-6c5faef11ec3.png)\r\n\r\n* `UPDATE_IN_PROGRESS` stack can be canceled(rollback) with `CancelUpdateStack` API\r\n* There's no `--disable-rollback` option for update stack\r\n\r\n### delete-stack\r\n![delete-stack](https://cloud.githubusercontent.com/assets/266641/9308723/8bce5020-4540-11e5-81a8-4fde233c40b8.png)\r\n\r\n* There's no rollback or abort flow for `DeleteStack` API \r\n* `DescribeStacks`'s `StackName` parameter can take either `StackName` or `StackID`.\r\n  For `DELETE_COMPLETE`-state stacks, `DescribeStacks`\r\n  * returns `ValidationError` when queried with `StackName`\r\n  * returns `DELETE_COMPLETE` status when queried with `StackID`\r\n\r\nOriginal graphviz gist files can be found here https://gist.github.com/quiver/e5496a91deda73bc9f84\r\n\r\n# Solves\r\n\r\n* aws/aws-cli#895\r\n* boto/boto3#84","created_at":"2015-08-17T16:02:15Z","updated_at":"2016-02-01T08:12:50Z","closed_at":null,"merged_at":null,"merge_commit_sha":"f3cd7ccc8cd67940cd215f5b4053961b955c6cb6","assignee":null,"milestone":null,"commits_url":"https://api.github.com/repos/boto/botocore/pulls/630/commits","review_comments_url":"https://api.github.com/repos/boto/botocore/pulls/630/comments","review_comment_url":"https://api.github.com/repos/boto/botocore/pulls/comments{/number}","comments_url":"https://api.github.com/repos/boto/botocore/issues/630/comments","statuses_url":"https://api.github.com/repos/boto/botocore/statuses/e4e76f73a4ce1a4183c6aeba969be84841c74fc2","head":{"label":"quiver:cfn-waiters","ref":"cfn-waiters","sha":"e4e76f73a4ce1a4183c6aeba969be84841c74fc2","user":{"login":"quiver","id":266641,"avatar_url":"https://avatars.githubusercontent.com/u/266641?v=3","gravatar_id":"","url":"https://api.github.com/users/quiver","html_url":"https://github.com/quiver","followers_url":"https://api.github.com/users/quiver/followers","following_url":"https://api.github.com/users/quiver/following{/other_user}","gists_url":"https://api.github.com/users/quiver/gists{/gist_id}","starred_url":"https://api.github.com/users/quiver/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/quiver/subscriptions","organizations_url":"https://api.github.com/users/quiver/orgs","repos_url":"https://api.github.com/users/quiver/repos","events_url":"https://api.github.com/users/quiver/events{/privacy}","received_events_url":"https://api.github.com/users/quiver/received_events","type":"User","site_admin":false},"repo":{"id":16662695,"name":"botocore","full_name":"quiver/botocore","owner":{"login":"quiver","id":266641,"avatar_url":"https://avatars.githubusercontent.com/u/266641?v=3","gravatar_id":"","url":"https://api.github.com/users/quiver","html_url":"https://github.com/quiver","followers_url":"https://api.github.com/users/quiver/followers","following_url":"https://api.github.com/users/quiver/following{/other_user}","gists_url":"https://api.github.com/users/quiver/gists{/gist_id}","starred_url":"https://api.github.com/users/quiver/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/quiver/subscriptions","organizations_url":"https://api.github.com/users/quiver/orgs","repos_url":"https://api.github.com/users/quiver/repos","events_url":"https://api.github.com/users/quiver/events{/privacy}","received_events_url":"https://api.github.com/users/quiver/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/quiver/botocore","description":"The low-level, core functionality of boto 3.","fork":true,"url":"https://api.github.com/repos/quiver/botocore","forks_url":"https://api.github.com/repos/quiver/botocore/forks","keys_url":"https://api.github.com/repos/quiver/botocore/keys{/key_id}","collaborators_url":"https://api.github.com/repos/quiver/botocore/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/quiver/botocore/teams","hooks_url":"https://api.github.com/repos/quiver/botocore/hooks","issue_events_url":"https://api.github.com/repos/quiver/botocore/issues/events{/number}","events_url":"https://api.github.com/repos/quiver/botocore/events","assignees_url":"https://api.github.com/repos/quiver/botocore/assignees{/user}","branches_url":"https://api.github.com/repos/quiver/botocore/branches{/branch}","tags_url":"https://api.github.com/repos/quiver/botocore/tags","blobs_url":"https://api.github.com/repos/quiver/botocore/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/quiver/botocore/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/quiver/botocore/git/refs{/sha}","trees_url":"https://api.github.com/repos/quiver/botocore/git/trees{/sha}","statuses_url":"https://api.github.com/repos/quiver/botocore/statuses/{sha}","languages_url":"https://api.github.com/repos/quiver/botocore/languages","stargazers_url":"https://api.github.com/repos/quiver/botocore/stargazers","contributors_url":"https://api.github.com/repos/quiver/botocore/contributors","subscribers_url":"https://api.github.com/repos/quiver/botocore/subscribers","subscription_url":"https://api.github.com/repos/quiver/botocore/subscription","commits_url":"https://api.github.com/repos/quiver/botocore/commits{/sha}","git_commits_url":"https://api.github.com/repos/quiver/botocore/git/commits{/sha}","comments_url":"https://api.github.com/repos/quiver/botocore/comments{/number}","issue_comment_url":"https://api.github.com/repos/quiver/botocore/issues/comments{/number}","contents_url":"https://api.github.com/repos/quiver/botocore/contents/{+path}","compare_url":"https://api.github.com/repos/quiver/botocore/compare/{base}...{head}","merges_url":"https://api.github.com/repos/quiver/botocore/merges","archive_url":"https://api.github.com/repos/quiver/botocore/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/quiver/botocore/downloads","issues_url":"https://api.github.com/repos/quiver/botocore/issues{/number}","pulls_url":"https://api.github.com/repos/quiver/botocore/pulls{/number}","milestones_url":"https://api.github.com/repos/quiver/botocore/milestones{/number}","notifications_url":"https://api.github.com/repos/quiver/botocore/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/quiver/botocore/labels{/name}","releases_url":"https://api.github.com/repos/quiver/botocore/releases{/id}","deployments_url":"https://api.github.com/repos/quiver/botocore/deployments","created_at":"2014-02-09T08:14:52Z","updated_at":"2015-04-01T15:44:55Z","pushed_at":"2015-11-14T04:07:23Z","git_url":"git://github.com/quiver/botocore.git","ssh_url":"git@github.com:quiver/botocore.git","clone_url":"https://github.com/quiver/botocore.git","svn_url":"https://github.com/quiver/botocore","homepage":null,"size":17514,"stargazers_count":0,"watchers_count":0,"language":"Python","has_issues":false,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":0,"mirror_url":null,"open_issues_count":0,"forks":0,"open_issues":0,"watchers":0,"default_branch":"develop"}},"base":{"label":"boto:develop","ref":"develop","sha":"0269685f34eaa7a2d982ba7cefea7b8ac7551a60","user":{"login":"boto","id":327752,"avatar_url":"https://avatars.githubusercontent.com/u/327752?v=3","gravatar_id":"","url":"https://api.github.com/users/boto","html_url":"https://github.com/boto","followers_url":"https://api.github.com/users/boto/followers","following_url":"https://api.github.com/users/boto/following{/other_user}","gists_url":"https://api.github.com/users/boto/gists{/gist_id}","starred_url":"https://api.github.com/users/boto/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/boto/subscriptions","organizations_url":"https://api.github.com/users/boto/orgs","repos_url":"https://api.github.com/users/boto/repos","events_url":"https://api.github.com/users/boto/events{/privacy}","received_events_url":"https://api.github.com/users/boto/received_events","type":"Organization","site_admin":false},"repo":{"id":6670942,"name":"botocore","full_name":"boto/botocore","owner":{"login":"boto","id":327752,"avatar_url":"https://avatars.githubusercontent.com/u/327752?v=3","gravatar_id":"","url":"https://api.github.com/users/boto","html_url":"https://github.com/boto","followers_url":"https://api.github.com/users/boto/followers","following_url":"https://api.github.com/users/boto/following{/other_user}","gists_url":"https://api.github.com/users/boto/gists{/gist_id}","starred_url":"https://api.github.com/users/boto/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/boto/subscriptions","organizations_url":"https://api.github.com/users/boto/orgs","repos_url":"https://api.github.com/users/boto/repos","events_url":"https://api.github.com/users/boto/events{/privacy}","received_events_url":"https://api.github.com/users/boto/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/boto/botocore","description":"The low-level, core functionality of boto 3.","fork":false,"url":"https://api.github.com/repos/boto/botocore","forks_url":"https://api.github.com/repos/boto/botocore/forks","keys_url":"https://api.github.com/repos/boto/botocore/keys{/key_id}","collaborators_url":"https://api.github.com/repos/boto/botocore/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/boto/botocore/teams","hooks_url":"https://api.github.com/repos/boto/botocore/hooks","issue_events_url":"https://api.github.com/repos/boto/botocore/issues/events{/number}","events_url":"https://api.github.com/repos/boto/botocore/events","assignees_url":"https://api.github.com/repos/boto/botocore/assignees{/user}","branches_url":"https://api.github.com/repos/boto/botocore/branches{/branch}","tags_url":"https://api.github.com/repos/boto/botocore/tags","blobs_url":"https://api.github.com/repos/boto/botocore/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/boto/botocore/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/boto/botocore/git/refs{/sha}","trees_url":"https://api.github.com/repos/boto/botocore/git/trees{/sha}","statuses_url":"https://api.github.com/repos/boto/botocore/statuses/{sha}","languages_url":"https://api.github.com/repos/boto/botocore/languages","stargazers_url":"https://api.github.com/repos/boto/botocore/stargazers","contributors_url":"https://api.github.com/repos/boto/botocore/contributors","subscribers_url":"https://api.github.com/repos/boto/botocore/subscribers","subscription_url":"https://api.github.com/repos/boto/botocore/subscription","commits_url":"https://api.github.com/repos/boto/botocore/commits{/sha}","git_commits_url":"https://api.github.com/repos/boto/botocore/git/commits{/sha}","comments_url":"https://api.github.com/repos/boto/botocore/comments{/number}","issue_comment_url":"https://api.github.com/repos/boto/botocore/issues/comments{/number}","contents_url":"https://api.github.com/repos/boto/botocore/contents/{+path}","compare_url":"https://api.github.com/repos/boto/botocore/compare/{base}...{head}","merges_url":"https://api.github.com/repos/boto/botocore/merges","archive_url":"https://api.github.com/repos/boto/botocore/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/boto/botocore/downloads","issues_url":"https://api.github.com/repos/boto/botocore/issues{/number}","pulls_url":"https://api.github.com/repos/boto/botocore/pulls{/number}","milestones_url":"https://api.github.com/repos/boto/botocore/milestones{/number}","notifications_url":"https://api.github.com/repos/boto/botocore/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/boto/botocore/labels{/name}","releases_url":"https://api.github.com/repos/boto/botocore/releases{/id}","deployments_url":"https://api.github.com/repos/boto/botocore/deployments","created_at":"2012-11-13T13:25:36Z","updated_at":"2016-01-30T02:18:39Z","pushed_at":"2016-01-30T01:10:43Z","git_url":"git://github.com/boto/botocore.git","ssh_url":"git@github.com:boto/botocore.git","clone_url":"https://github.com/boto/botocore.git","svn_url":"https://github.com/boto/botocore","homepage":null,"size":21374,"stargazers_count":218,"watchers_count":218,"language":"Python","has_issues":true,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":137,"mirror_url":null,"open_issues_count":29,"forks":137,"open_issues":29,"watchers":218,"default_branch":"develop"}},"_links":{"self":{"href":"https://api.github.com/repos/boto/botocore/pulls/630"},"html":{"href":"https://github.com/boto/botocore/pull/630"},"issue":{"href":"https://api.github.com/repos/boto/botocore/issues/630"},"comments":{"href":"https://api.github.com/repos/boto/botocore/issues/630/comments"},"review_comments":{"href":"https://api.github.com/repos/boto/botocore/pulls/630/comments"},"review_comment":{"href":"https://api.github.com/repos/boto/botocore/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/boto/botocore/pulls/630/commits"},"statuses":{"href":"https://api.github.com/repos/boto/botocore/statuses/e4e76f73a4ce1a4183c6aeba969be84841c74fc2"}}}}