コード例 #1
0
    def fetch(
        self,
        fields: Optional[List[str]] = None,
        update: bool = True,
        fetch_aa_data: bool = False,
    ) -> None:
        if self._dirty:
            raise IntegrityError(
                "role object has unsaved modifications, fetching may overwrite changes"
            )

        if self.role_id:
            stored_role_data = get_role_by_id(self.role_id, fields=fields)
        elif self.arn:
            stored_role_data = get_role_by_arn(self.arn, fields=fields)
        else:
            # TODO: we can pull role_name and account from an ARN, support that too
            raise ModelError(
                "missing role_id or role_name and account on Role instance")

        if update:
            self.update(stored_role_data, store=False, dirty=False)
            self._updated_fields - set(stored_role_data.keys())
            if fetch_aa_data:
                self.fetch_aa_data()
コード例 #2
0
    def fetch(self,
              fields: Optional[List[str]] = None,
              update: bool = True) -> None:
        if self._dirty:
            raise IntegrityError(
                "role object has unsaved modifications, fetching may overwrite changes"
            )

        if self.role_id:
            stored_role_data = get_role_by_id(self.role_id, fields=fields)
        elif self.role_name and self.account:
            stored_role_data = get_role_by_name(self.account,
                                                self.role_name,
                                                fields=fields)
        else:
            raise ModelError(
                "missing role_id or role_name and account on Role instance")

        if update:
            self.update(stored_role_data, store=False)
            self._updated_fields - set(stored_role_data.keys())
コード例 #3
0
    def store(self, fields: Optional[List[str]] = None) -> None:
        create = False
        try:
            remote_role_data = Role(role_id=self.role_id, arn=self.arn)
            remote_role_data.fetch(fields=["LastUpdated"])
            if (remote_role_data.last_updated and self.last_updated
                    and remote_role_data.last_updated > self.last_updated):
                raise IntegrityError(
                    "stored role has been updated since last fetch")
        except RoleNotFoundError:
            create = True

        self.last_updated = datetime.datetime.now()

        if create:
            # TODO: handle this case in set_role_data() to simplify logic here
            create_dynamodb_entry(
                self.dict(by_alias=True,
                          exclude={"config", "_dirty", "_updated_fields"}))
            self._updated_fields = set()
        else:
            if fields:
                include_fields = set(fields)
                include_fields.add("last_updated")
                set_role_data(
                    self.role_id,
                    self.dict(
                        include=include_fields,
                        by_alias=True,
                        exclude=self._default_exclude,
                    ),
                )
                self._updated_fields - set(fields)
            else:
                set_role_data(
                    self.role_id,
                    self.dict(by_alias=True, exclude=self._default_exclude),
                )
                self._updated_fields = set()
        self._dirty = False
コード例 #4
0
    def store(self, fields: Optional[List[str]] = None) -> None:
        create = False
        try:
            remote_role_data = Role(role_id=self.role_id, arn=self.arn)
            remote_role_data.fetch(fields=["LastUpdated"])
            if (remote_role_data.last_updated and self.last_updated
                    and remote_role_data.last_updated > self.last_updated):
                # Fetch the rest of the role data for debugging
                remote_role_data.fetch()
                logger.warning(
                    "role has been updated since last fetch: stored %s, local %s",
                    remote_role_data.last_updated,
                    self.last_updated,
                    extra={
                        "stored_role": remote_role_data.dict(),
                        "local_role": self.dict(),
                    },
                )
                raise IntegrityError(
                    "stored role has been updated since last fetch")
        except RoleNotFoundError:
            create = True

        self.last_updated = datetime.datetime.now()

        set_role_data_args: Dict[str, Any] = {
            "by_alias": True,
        }
        # If fields are specified, we need to add last_updated to make sure it gets set
        if fields:
            include_fields = set(fields)
            include_fields.add("last_updated")
            set_role_data_args["include"] = include_fields

        # Exclude key fields unless this is a newly-created item. Key fields cannot be included
        # in DynamoDB update calls.
        exclude_fields = self._meta
        if not create:
            exclude_fields.update(self._keys)
        set_role_data_args["exclude"] = exclude_fields

        attempts = 0
        max_retries = 3
        while attempts < max_retries:
            try:
                set_role_data(
                    self.role_id,
                    self.dict(**set_role_data_args),
                    create=create,
                )
                self._updated_fields = (self._updated_fields -
                                        set(fields) if fields else set())
                # model is still dirty if we haven't stored all updated fields
                self._dirty = len(self._updated_fields) > 0
                return
            except DynamoDBMaxItemSizeError:
                logger.info(
                    "role %s too big for DynamoDB, removing oldest policy version",
                    self.role_name,
                )
                self._remove_oldest_policy_version()
                attempts += 1
                continue
            except DynamoDBError:
                logger.info(
                    "failed attempt %d to store role %s in DynamoDB",
                    attempts,
                    self.role_name,
                    exc_info=True,
                )
                attempts += 1
                continue
        # If we've made it this far, the role was not stored
        raise RoleStoreError(f"failed to store {self.arn} in DynamoDB")