def list_clusters(region=None, next_token=None, cluster_status=None): """ Retrieve the list of existing clusters managed by the API. Deleted clusters are not listed by default. :param region: List clusters deployed to a given AWS Region. :type region: str :param next_token: Token to use for paginated requests. :type next_token: str :param cluster_status: Filter by cluster status. (Defaults to all clusters.) :type cluster_status: list | bytes :rtype: ListClustersResponseContent """ stacks, next_token = AWSApi.instance().cfn.list_pcluster_stacks(next_token=next_token) stacks = [ClusterStack(stack) for stack in stacks] clusters = [] for stack in stacks: current_cluster_status = cloud_formation_status_to_cluster_status(stack.status) if not cluster_status or current_cluster_status in cluster_status: cluster_info = ClusterInfoSummary( cluster_name=stack.cluster_name, cloudformation_stack_status=stack.status, cloudformation_stack_arn=stack.id, region=os.environ.get("AWS_DEFAULT_REGION"), version=stack.version, cluster_status=current_cluster_status, ) clusters.append(cluster_info) return ListClustersResponseContent(clusters=clusters, next_token=next_token)
def test_validate_empty_change_set(self, mocker, force): mock_aws_api(mocker) cluster = Cluster( FAKE_NAME, stack=ClusterStack({ "StackName": FAKE_NAME, "CreationTime": "2021-06-04 10:23:20.199000+00:00", "StackStatus": ClusterStatus.CREATE_COMPLETE, }), config=OLD_CONFIGURATION, ) mocker.patch("pcluster.aws.cfn.CfnClient.stack_exists", return_value=True) if force: _, changes, _ = cluster.validate_update_request( target_source_config=OLD_CONFIGURATION, validator_suppressors={AllValidatorsSuppressor()}, force=force, ) assert_that(changes).is_length(1) else: with pytest.raises( BadRequestClusterActionError, match="No changes found in your cluster configuration."): cluster.validate_update_request( target_source_config=OLD_CONFIGURATION, validator_suppressors={AllValidatorsSuppressor()}, force=force, )
def cluster(self, mocker): mocker.patch( "pcluster.models.cluster.Cluster.bucket", new_callable=PropertyMock( return_value=S3Bucket( service_name=FAKE_NAME, stack_name=FAKE_NAME, artifact_directory=ARTIFACT_DIRECTORY ) ), ) return Cluster( FAKE_NAME, stack=ClusterStack({"StackName": FAKE_NAME, "CreationTime": "2021-06-04 10:23:20.199000+00:00"}) )
def delete(self, keep_logs: bool = True): """Delete cluster preserving log groups.""" try: if keep_logs: self._persist_cloudwatch_log_groups() self.stack.delete() self.__stack = ClusterStack(AWSApi.instance().cfn.describe_stack( self.stack_name)) except StackNotFoundError: raise except Exception as e: self.terminate_nodes() raise _cluster_error_mapper( e, f"Cluster {self.name} did not delete successfully. {e}")
def update( self, target_source_config: str, validator_suppressors: Set[ValidatorSuppressor] = None, validation_failure_level: FailureLevel = FailureLevel.ERROR, force: bool = False, ): """ Update cluster. raises ClusterActionError: in case of generic error raises ConfigValidationError: if configuration is invalid raises ClusterUpdateError: if update is not allowed """ try: target_config, changes, ignored_validation_failures = self.validate_update_request( target_source_config, validator_suppressors, validation_failure_level, force) self.config = target_config self.__source_config_text = target_source_config self._add_version_tag() self._upload_config() # Create template if not provided by the user if not (self.config.dev_settings and self.config.dev_settings.cluster_template): self.template_body = CDKTemplateBuilder( ).build_cluster_template( cluster_config=self.config, bucket=self.bucket, stack_name=self.stack_name, log_group_name=self.stack.log_group_name, ) # upload cluster artifacts and generated template self._upload_artifacts() LOGGER.info("Updating stack named: %s", self.stack_name) AWSApi.instance().cfn.update_stack_from_url( stack_name=self.stack_name, template_url=self.bucket.get_cfn_template_url( template_name=PCLUSTER_S3_ARTIFACTS_DICT.get( "template_name")), tags=self._get_cfn_tags(), ) self.__stack = ClusterStack(AWSApi.instance().cfn.describe_stack( self.stack_name)) LOGGER.debug("StackId: %s", self.stack.id) LOGGER.info("Status: %s", self.stack.status) return changes, ignored_validation_failures except ClusterActionError as e: # It can be a ConfigValidationError or ClusterUpdateError raise e except Exception as e: LOGGER.critical(e) raise _cluster_error_mapper(e, f"Cluster update failed.\n{e}")
def stack(self): """Return the ClusterStack object.""" if not self.__stack: self.__stack = ClusterStack(AWSApi.instance().cfn.describe_stack( self.stack_name)) return self.__stack