def sync(config, group, accounts=(), dryrun=False, region=None):
    """sync last recorded export to actual

    Use --dryrun to check status.
    """
    config = validate.callback(config)
    destination = config.get('destination')
    client = boto3.Session().client('s3')

    for account in config.get('accounts', ()):
        if accounts and account['name'] not in accounts:
            continue

        session = get_session(account['role'], region)
        account_id = session.client('sts').get_caller_identity()['Account']
        prefix = destination.get('prefix', '').rstrip('/') + '/%s' % account_id
        prefix = "%s/%s" % (prefix, group)

        exports = get_exports(client, destination['bucket'], prefix + "/")

        role = account.pop('role')
        if isinstance(role, six.string_types):
            account['account_id'] = role.split(':')[4]
        else:
            account['account_id'] = role[-1].split(':')[4]
        account.pop('groups')

        if exports:
            last_export = exports.pop()
            account['export'] = last_export
        else:
            account['export'] = 'missing'
            last_export = None
        try:
            tag_set = client.get_object_tagging(
                Bucket=destination['bucket'], Key=prefix).get('TagSet', [])
        except ClientError:
            tag_set = []

        tags = {t['Key']: t['Value'] for t in tag_set}
        tagged_last_export = None

        if 'LastExport' in tags:
            le = parse(tags['LastExport'])
            tagged_last_export = (le.year, le.month, le.day)
            account['sync'] = tagged_last_export
        else:
            account['sync'] = account['export'] != 'missing' and 'sync' or 'missing'

        if last_export is None:
            continue

        if tagged_last_export == last_export or account['export'] == 'missing':
            continue

        if dryrun:
            continue

        client.put_object(
            Bucket=destination['bucket'],
            Key=prefix,
            Body=json.dumps({}),
            ACL="bucket-owner-full-control",
            ServerSideEncryption="AES256")

        export_time = datetime.now().replace(tzinfo=tzlocal()).astimezone(tzutc())
        export_time = export_time.replace(
            year=last_export[0], month=last_export[1], day=last_export[2],
            minute=0, second=0, microsecond=0, hour=0)
        client.put_object_tagging(
            Bucket=destination['bucket'], Key=prefix,
            Tagging={
                'TagSet': [{
                    'Key': 'LastExport',
                    'Value': export_time.isoformat()}]})

    accounts_report = []
    for a in config.get('accounts'):
        if accounts and a['name'] not in accounts:
            continue
        if isinstance(a['sync'], tuple):
            a['sync'] = "%s/%s/%s" % (a['sync'])
        if isinstance(a['export'], tuple):
            a['export'] = "%s/%s/%s" % (a['export'])
        accounts_report.append(a)

    accounts_report.sort(key=operator.itemgetter('export'), reverse=True)
    print(tabulate(accounts_report, headers='keys'))
def sync ( config , group , accounts = ( ) , dryrun = False , region = None ) : config = validate . callback ( config ) destination = config . get ( 'destination' ) client = boto3 . Session ( ) . client ( 's3' ) for account in config . get ( 'accounts' , ( ) ) : if accounts and account [ 'name' ] not in accounts : continue session = get_session ( account [ 'role' ] , region ) account_id = session . client ( 'sts' ) . get_caller_identity ( ) [ 'Account' ] prefix = destination . get ( 'prefix' , '' ) . rstrip ( '/' ) + '/%s' % account_id prefix = "%s/%s" % ( prefix , group ) exports = get_exports ( client , destination [ 'bucket' ] , prefix + "/" ) role = account . pop ( 'role' ) if isinstance ( role , six . string_types ) : account [ 'account_id' ] = role . split ( ':' ) [ 4 ] else : account [ 'account_id' ] = role [ - 1 ] . split ( ':' ) [ 4 ] account . pop ( 'groups' ) if exports : last_export = exports . pop ( ) account [ 'export' ] = last_export else : account [ 'export' ] = 'missing' last_export = None try : tag_set = client . get_object_tagging ( Bucket = destination [ 'bucket' ] , Key = prefix ) . get ( 'TagSet' , [ ] ) except ClientError : tag_set = [ ] tags = { t [ 'Key' ] : t [ 'Value' ] for t in tag_set } tagged_last_export = None if 'LastExport' in tags : le = parse ( tags [ 'LastExport' ] ) tagged_last_export = ( le . year , le . month , le . day ) account [ 'sync' ] = tagged_last_export else : account [ 'sync' ] = account [ 'export' ] != 'missing' and 'sync' or 'missing' if last_export is None : continue if tagged_last_export == last_export or account [ 'export' ] == 'missing' : continue if dryrun : continue client . put_object ( Bucket = destination [ 'bucket' ] , Key = prefix , Body = json . dumps ( { } ) , ACL = "bucket-owner-full-control" , ServerSideEncryption = "AES256" ) export_time = datetime . now ( ) . replace ( tzinfo = tzlocal ( ) ) . astimezone ( tzutc ( ) ) export_time = export_time . replace ( year = last_export [ 0 ] , month = last_export [ 1 ] , day = last_export [ 2 ] , minute = 0 , second = 0 , microsecond = 0 , hour = 0 ) client . put_object_tagging ( Bucket = destination [ 'bucket' ] , Key = prefix , Tagging = { 'TagSet' : [ { 'Key' : 'LastExport' , 'Value' : export_time . isoformat ( ) } ] } ) accounts_report = [ ] for a in config . get ( 'accounts' ) : if accounts and a [ 'name' ] not in accounts : continue if isinstance ( a [ 'sync' ] , tuple ) : a [ 'sync' ] = "%s/%s/%s" % ( a [ 'sync' ] ) if isinstance ( a [ 'export' ] , tuple ) : a [ 'export' ] = "%s/%s/%s" % ( a [ 'export' ] ) accounts_report . append ( a ) accounts_report . sort ( key = operator . itemgetter ( 'export' ) , reverse = True ) print ( tabulate ( accounts_report , headers = 'keys' ) )
sync last recorded export to actual

    Use --dryrun to check status.