Assemble a document representing all the config state around a bucket.

    TODO: Refactor this, the logic here feels quite muddled.

def assemble_bucket(item):
    """Assemble a document representing all the config state around a bucket.

    TODO: Refactor this, the logic here feels quite muddled.
    """
    factory, b = item
    s = factory()
    c = s.client('s3')
    # Bucket Location, Current Client Location, Default Location
    b_location = c_location = location = "us-east-1"
    methods = list(S3_AUGMENT_TABLE)
    for m, k, default, select in methods:
        try:
            method = getattr(c, m)
            v = method(Bucket=b['Name'])
            v.pop('ResponseMetadata')
            if select is not None and select in v:
                v = v[select]
        except (ssl.SSLError, SSLError) as e:
            # Proxy issues? i assume
            log.warning("Bucket ssl error %s: %s %s",
                        b['Name'], b.get('Location', 'unknown'),
                        e)
            continue
        except ClientError as e:
            code = e.response['Error']['Code']
            if code.startswith("NoSuch") or "NotFound" in code:
                v = default
            elif code == 'PermanentRedirect':
                s = factory()
                c = bucket_client(s, b)
                # Requeue with the correct region given location constraint
                methods.append((m, k, default, select))
                continue
            else:
                log.warning(
                    "Bucket:%s unable to invoke method:%s error:%s ",
                    b['Name'], m, e.response['Error']['Message'])
                # For auth failures, we don't bail out, continue processing if we can.
                # Note this can lead to missing data, but in general is cleaner than
                # failing hard, due to the common use of locked down s3 bucket policies
                # that may cause issues fetching information across a fleet of buckets.

                # This does mean s3 policies depending on augments should check denied
                # methods annotation, generally though lacking get access to an augment means
                # they won't have write access either.

                # For other error types we raise and bail policy execution.
                if e.response['Error']['Code'] == 'AccessDenied':
                    b.setdefault('c7n:DeniedMethods', []).append(m)
                    continue
                raise
        # As soon as we learn location (which generally works)
        if k == 'Location' and v is not None:
            b_location = v.get('LocationConstraint')
            # Location == region for all cases but EU
            # https://docs.aws.amazon.com/AmazonS3/latest/API/RESTBucketGETlocation.html
            if b_location is None:
                b_location = "us-east-1"
            elif b_location == 'EU':
                b_location = "eu-west-1"
                v['LocationConstraint'] = 'eu-west-1'
            if v and v != c_location:
                c = s.client('s3', region_name=b_location)
            elif c_location != location:
                c = s.client('s3', region_name=location)
        b[k] = v
    return b