Exemplo n.º 1
0
 def from_response(cls, details: Dict) -> ContainerInstance:
     return cls(
         arn=query("containerInstanceArn", details),
         status=query("status", details),
         ec2id=query("ec2InstanceId", details),
         registered_at=query("registeredAt", details),
         agent_connected=query("agentConnected", details),
         details=details,
     )
Exemplo n.º 2
0
 def terminate(self) -> Tuple[str, str]:
     instance = self.ec2_instance
     response = instance.terminate()
     raise_for_status(response)
     state = query("TerminatingInstances.0.CurrentState.Name", response)
     logger.info(f"terminated {instance.id}: state={state}")
     return instance.id, state
Exemplo n.º 3
0
 def instances(self) -> List[ContainerInstance]:
     response = self.client.describe_container_instances(
         cluster=self.cluster_name,
         containerInstances=self._container_instance_arns)
     raise_for_status(response)
     instances = query("containerInstances", response) or []
     return [ContainerInstance.from_response(ins) for ins in instances]
Exemplo n.º 4
0
 def ipv4(self) -> str:
     return reduce(  # type: ignore
         [
             x["value"]
             for x in query("attachments.0.details", self._details)
             if x["name"] == "privateIPv4Address"
         ])
Exemplo n.º 5
0
def raise_for_status(response: dict, ok_codes: Union[int, List[int]] = 200):
    status_code = query("ResponseMetadata.HTTPStatusCode", response)
    if status_code is None:
        raise ValueError(
            f"Couldn't determine status_code from response: {response=}")
    if status_code not in ensure_list(ok_codes):
        raise HTTPResponseError(
            f"Request returned invalid response code: {status_code}")
Exemplo n.º 6
0
    def __init__(self, cluster: str, client: boto3.client = None):
        """ Get details about and issue various commands to an ECS cluster

        Arguments:
            cluster {str} -- cluster name or arn

        Keyword Arguments:
            client {boto3.client} -- instance of boto3.client('ecs') (default: None)
        """

        self.cluster_name = cluster.split("/")[-1] if "/" else cluster
        self.client = client or boto3.client("ecs")
        details = self._cluster_details
        self.arn = query("clusterArn", details)
        self.instance_count = query("registeredContainerInstancesCount",
                                    details)
        self.services = query("activeServicesCount", details)
        self.tasks = query("runningTasksCount", details)
Exemplo n.º 7
0
    def account_id(self) -> str:
        if self._account_id is None:
            payload = sts.get_caller_identity()
            sts_response_code = query("ResponseMetadata.HTTPStatusCode", data=payload)

            if sts_response_code != 200:
                raise ValueError(f"({self.iam_username}) failed to fetch account id")

            self._account_id = payload["Account"]

        return self._account_id
Exemplo n.º 8
0
    def delete_key(self, access_key_id: str):
        payload = iam.delete_access_key(
            UserName=self.iam_username, AccessKeyId=access_key_id
        )

        response_code = query("ResponseMetadata.HTTPStatusCode", data=payload)

        if response_code == 200:
            logger.info(f"({self.iam_username}) deleted old access key")
        else:
            raise ValueError(f"({self.iam_username}) failed to delete old access key")
Exemplo n.º 9
0
    def create_new_credentials(self, is_retry: bool = False) -> Dict[str, str]:
        if not self.new:
            try:
                payload = iam.create_access_key(UserName=self.iam_username)
            except iam.exceptions.LimitExceededException as e:
                logger.warning(f"({self.iam_username}) -- {e}")
                oldest = self.oldest_key
                if oldest:
                    self.delete_key(oldest)
                    logger.warning(
                        f"({self.iam_username}) retrying creating new credentials"
                    )
                    if not is_retry:  # only retry once
                        return self.create_new_credentials(is_retry=True)

            response_code = query("ResponseMetadata.HTTPStatusCode", data=payload)

            if response_code == 200:
                logger.info(f"({self.iam_username}) created new access key")
            else:
                raise ValueError(
                    f"({self.iam_username}) failed to create new access key"
                )

            access_key = payload["AccessKey"]
            self._next_key_id = access_key["AccessKeyId"]

            self.new = {
                "AWS_ACCOUNT_ID": self.account_id,
                "AWS_ACCESS_KEY_ID": access_key["AccessKeyId"],
                "AWS_SECRET_ACCESS_KEY": access_key["SecretAccessKey"],
                "AWS_IAM_ROLE": access_key["UserName"],
                "LAST_ROTATED": str(date.today()),
            }

            return self.new
        else:
            raise ValueError(f"credentials have already been generated")
Exemplo n.º 10
0
 def _container_instance_arns(self) -> List[str]:
     response = self.client.list_container_instances(
         cluster=self.cluster_name)
     raise_for_status(response)
     return query("containerInstanceArns", response) or []
Exemplo n.º 11
0
 def _cluster_details(self) -> Dict:
     response = self.client.describe_clusters(clusters=[self.cluster_name])
     raise_for_status(response)
     cluster: Dict = reduce(query("clusters", response))  # type: ignore
     return cluster
Exemplo n.º 12
0
def test_query_nested_collection(queryable):
    expected = "example_full"
    assert it.query("slim.tasks.1.name", data=queryable) == expected
Exemplo n.º 13
0
 def _fetch_access_key(self, oldest: bool = False):
     payload = iam.list_access_keys(UserName=self.iam_username)
     index = -1 if oldest else 0
     return query(f"AccessKeyMetadata.{index}.AccessKeyId", data=payload)