Mercurial > public > mercurial-scm > hg
comparison contrib/automation/hgautomation/aws.py @ 42278:8dc22a209420
automation: wait for instance profiles and roles
Otherwise there is a race condition between creating the resources
and us attempting to use them / them becoming available.
The role waiter API was recently introduced, so we had to upgrade
the boto3 package to get it. Other packages were also updated
to latest versions just because.
Even with this change, I still run into issues with the IAM instance
profile not being available when we attempt to create an EC2 instance
using a just-created profile. I'm not sure what's going on. Possibly
a bug on Amazon's end. But the new behavior is "more correct."
Differential Revision: https://phab.mercurial-scm.org/D6286
author | Gregory Szorc <gregory.szorc@gmail.com> |
---|---|
date | Sat, 27 Apr 2019 11:38:58 -0700 |
parents | dd6a9723ae2b |
children | e570106beda1 |
comparison
equal
deleted
inserted
replaced
42277:dd6a9723ae2b | 42278:8dc22a209420 |
---|---|
194 self.security_groups = {} | 194 self.security_groups = {} |
195 | 195 |
196 if ensure_ec2_state: | 196 if ensure_ec2_state: |
197 ensure_key_pairs(automation.state_path, self.ec2resource) | 197 ensure_key_pairs(automation.state_path, self.ec2resource) |
198 self.security_groups = ensure_security_groups(self.ec2resource) | 198 self.security_groups = ensure_security_groups(self.ec2resource) |
199 ensure_iam_state(self.iamresource) | 199 ensure_iam_state(self.iamclient, self.iamresource) |
200 | 200 |
201 def key_pair_path_private(self, name): | 201 def key_pair_path_private(self, name): |
202 """Path to a key pair private key file.""" | 202 """Path to a key pair private key file.""" |
203 return self.local_state_path / 'keys' / ('keypair-%s' % name) | 203 return self.local_state_path / 'keys' / ('keypair-%s' % name) |
204 | 204 |
323 | 323 |
324 print('deleting instance profile %s' % profile.name) | 324 print('deleting instance profile %s' % profile.name) |
325 profile.delete() | 325 profile.delete() |
326 | 326 |
327 | 327 |
328 def ensure_iam_state(iamresource, prefix='hg-'): | 328 def ensure_iam_state(iamclient, iamresource, prefix='hg-'): |
329 """Ensure IAM state is in sync with our canonical definition.""" | 329 """Ensure IAM state is in sync with our canonical definition.""" |
330 | 330 |
331 remote_profiles = {} | 331 remote_profiles = {} |
332 | 332 |
333 for profile in iamresource.instance_profiles.all(): | 333 for profile in iamresource.instance_profiles.all(): |
359 | 359 |
360 profile = iamresource.create_instance_profile( | 360 profile = iamresource.create_instance_profile( |
361 InstanceProfileName=actual) | 361 InstanceProfileName=actual) |
362 remote_profiles[name] = profile | 362 remote_profiles[name] = profile |
363 | 363 |
364 waiter = iamclient.get_waiter('instance_profile_exists') | |
365 waiter.wait(InstanceProfileName=actual) | |
366 print('IAM instance profile %s is available' % actual) | |
367 | |
364 for name in sorted(set(IAM_ROLES) - set(remote_roles)): | 368 for name in sorted(set(IAM_ROLES) - set(remote_roles)): |
365 entry = IAM_ROLES[name] | 369 entry = IAM_ROLES[name] |
366 | 370 |
367 actual = '%s%s' % (prefix, name) | 371 actual = '%s%s' % (prefix, name) |
368 print('creating IAM role %s' % actual) | 372 print('creating IAM role %s' % actual) |
370 role = iamresource.create_role( | 374 role = iamresource.create_role( |
371 RoleName=actual, | 375 RoleName=actual, |
372 Description=entry['description'], | 376 Description=entry['description'], |
373 AssumeRolePolicyDocument=ASSUME_ROLE_POLICY_DOCUMENT, | 377 AssumeRolePolicyDocument=ASSUME_ROLE_POLICY_DOCUMENT, |
374 ) | 378 ) |
379 | |
380 waiter = iamclient.get_waiter('role_exists') | |
381 waiter.wait(RoleName=actual) | |
382 print('IAM role %s is available' % actual) | |
375 | 383 |
376 remote_roles[name] = role | 384 remote_roles[name] = role |
377 | 385 |
378 for arn in entry['policy_arns']: | 386 for arn in entry['policy_arns']: |
379 print('attaching policy %s to %s' % (arn, role.name)) | 387 print('attaching policy %s to %s' % (arn, role.name)) |