Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/361.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python Boto:检查是否存在CloudFormation堆栈的最佳方法是什么?_Python_Amazon Web Services_Boto_Amazon Cloudformation - Fatal编程技术网

Python Boto:检查是否存在CloudFormation堆栈的最佳方法是什么?

Python Boto:检查是否存在CloudFormation堆栈的最佳方法是什么?,python,amazon-web-services,boto,amazon-cloudformation,Python,Amazon Web Services,Boto,Amazon Cloudformation,使用Boto检查CloudFormation堆栈是否存在且未处于损坏状态的最佳方法是什么?我所说的中断是指失败和回滚状态 我不想使用try/except解决方案,因为boto会将其记录为错误,在我的场景中,它会将异常日志发送到报警系统 目前,我有以下解决方案: 1) 使用 这是缓慢的,因为我有很多堆栈 2) 使用 这要花很长时间,因为总结要保存90天,而且我有很多堆栈 问题:检查给定堆栈是否存在且未处于故障或回滚状态的理想解决方案是什么?来自boto文档: 描述\u堆栈(堆栈\u名称\u或

使用Boto检查CloudFormation堆栈是否存在且未处于损坏状态的最佳方法是什么?我所说的中断是指失败和回滚状态

我不想使用
try/except
解决方案,因为boto会将其记录为错误,在我的场景中,它会将异常日志发送到报警系统


目前,我有以下解决方案:

1) 使用

这是缓慢的,因为我有很多堆栈


2) 使用

这要花很长时间,因为总结要保存90天,而且我有很多堆栈


问题:检查给定堆栈是否存在且未处于故障或回滚状态的理想解决方案是什么?

来自boto文档:

描述\u堆栈(堆栈\u名称\u或\u id=None,下一个\u标记=None)

返回指定堆栈的描述;如果未指定堆栈名称,则返回所创建的所有堆栈的描述

参数:堆栈\名称\或\ id(字符串)–与堆栈关联的名称或唯一标识符


由于您知道堆栈名称,因此可以使用
描述堆栈(stack\u name\u或\u id=stack\u name)
。这将加快您的速度。

最好的方法是将其分为两个独立的问题:

  • 找出哪些堆栈不存在
  • 找出哪些堆栈处于错误状态
  • 可能看起来像这样:

    failure_states = ['CREATE_FAILED', ... ]
    stack_names = ['prod', 'dev', 'test']
    
    c = boto.cloudformation.connect_to_region(region)
    existing_stacks = [s.stack_name for s in c.describe_stacks()]
    nonexistent_stacks = set(stack_names) - set(existing_stacks)
    error_stacks = c.list_stacks(stack_status_filters=failure_states) 
    

    您可能有更多的堆栈,然后我这样做,也许您需要使用
    next\u token
    进行分页,这会有点麻烦。但是,您可以看到,这两个操作都可以通过单个请求完成,并且不会引发异常。

    我知道这很旧,但几周前有人问是否有解决方案,因此

    如果你阅读boto3文档,它会经常提到已删除的堆栈。为此,必须使用完整堆栈ID。不能使用堆栈名称。这是因为堆栈唯一真正独特的地方是ID

    例如:

    resource = boto3.resource('cloudformation')
    status = resource.Stack('id:of:stack').stack_status
    
    这将返回异常的唯一时间是堆栈ID不存在的情况


    干杯

    通过将Boto记录器的级别设置为高于错误,可以使其静音。这将允许您捕获异常,而无需记录警报:

    import boto3
    import botocore.exceptions
    import logging
    
    cf = boto3.resource('cloudformation')
    logging.Logger.manager.loggerDict['boto3'].setLevel(logging.CRITICAL)
    logging.Logger.manager.loggerDict['botocore'].setLevel(logging.CRITICAL)
    try:
        stack.Stack('foo').stack_status
    except botocore.exceptions.ClientError:
        logging.info('stack doesnt exist')
    
    logging.Logger.manager.loggerDict['boto3'].setLevel(logging.WARNING)
    logging.Logger.manager.loggerDict['botocore'].setLevel(logging.WARNING)
    

    我实施了以下工作:

    import boto3
    from botocore.exceptions import ClientError
    
    client = boto3.client('cloudformation')
    
    def stack_exists(name, required_status = 'CREATE_COMPLETE'):
        try:
            data = client.describe_stacks(StackName = name)
        except ClientError:
            return False
        return data['Stacks'][0]['StackStatus'] == required_status
    

    我没有发现以前的任何解决方案是完整的,也没有任何快速的方法可以使用boto3来完成,所以我创建了上面的解决方案。

    我会通过paginator结合API调用进行检查,因为如果发生这种情况,可能是我的lambda或我没有
    cloudformation
    的权限,我应该返回相关信息,而不是说堆栈不存在

    导入boto3
    从botocore.exceptions导入ClientError
    cfn=boto3.client('cloudformation')
    def stack_存在(stack_名称:str,stack_状态:str)->bool:
    尝试:
    paginator=cfn.get_paginator('list_stacks'))
    response_iterator=paginator.paginate()
    对于响应迭代器中的页面:
    对于第['StackSummaries']页中的堆栈:
    如果stack_name==stack.get('StackName')和stack.get('StackStatus')!=堆栈状态:
    返回真值
    除ClientError作为e外:
    异常(f'检查堆栈时出现客户端错误:{e}')
    提升
    除例外情况外:
    logger.exception('检查堆栈时出错')
    提升
    返回错误
    
    或者,如果我们不想迭代所有堆栈:

    导入boto3
    从botocore.exceptions导入ClientError
    cfn=boto3.client('cloudformation')
    def堆栈_存在(堆栈_名称:str,必需_status='DELETE_COMPLETE'):
    尝试:
    stacks\u summary=cfn.描述\u堆栈(StackName=stack\u name)
    stack\u info=stacks\u summary.get('stacks')[0]
    返回stack_name==stack_info.get('StackName')和stack_info.get('StackStatus')!=所需的_状态
    除ClientError作为e外:
    stack_not_found_error=f'id为{stack_name}的堆栈不存在'
    接收到的错误=e.response('错误')
    error\u code\u received=error\u received.get('code'))
    error\u message\u received=error\u received.get('message')
    如果错误\u代码\u接收==“ValidationError”和错误\u消息\u接收==堆栈\u未找到\u错误:
    返回真值
    异常(描述堆栈时出现f'客户端错误:{e}')
    提升
    除例外情况外:
    logger.exception('检查堆栈时出错')
    提升
    
    如果堆栈不存在,它会引发异常,正如我所说的,仅使用try/except是不够的,因为boto会将其记录为错误,如果我的警报系统看到错误日志,它会收到通知。谢谢,但这还不够。@HugoTavares。为了解决这个问题,我使用
    waterer
    等待
    stack\u存在
    ,只进行一次尝试(),并捕获
    ToomanyAttestError
    ,以防其他人试图找出它。。最新版本中正确的错误是botocore.exceptions.waiterror。感谢您的回答@liyan chang,但是您的第一个问题的答案是无限的。我的代码对现有堆栈一无所知,我想知道是否存在给定的堆栈。通过[s.stack\u c.descripe\u stacks()中s的名称]中的Boto?'ABC',检查CloudFormation中是否存在堆栈“ABC”的最佳方法是什么?但是如果有许多堆栈,这可能会很慢。。。我在问题文本中有这个答案。啊。你现在处境艰难。如果无法列出所有堆栈,则必须尝试/排除异常并处理它。如果列表堆栈接受堆栈名称列表过滤器,那将非常好。你找到解决这个问题的方法了吗?@bdrx:没有,自从我发布这个问题的那周起,我就没有找到其他的解决方法。
    import boto3
    import botocore.exceptions
    import logging
    
    cf = boto3.resource('cloudformation')
    logging.Logger.manager.loggerDict['boto3'].setLevel(logging.CRITICAL)
    logging.Logger.manager.loggerDict['botocore'].setLevel(logging.CRITICAL)
    try:
        stack.Stack('foo').stack_status
    except botocore.exceptions.ClientError:
        logging.info('stack doesnt exist')
    
    logging.Logger.manager.loggerDict['boto3'].setLevel(logging.WARNING)
    logging.Logger.manager.loggerDict['botocore'].setLevel(logging.WARNING)
    
    import boto3
    from botocore.exceptions import ClientError
    
    client = boto3.client('cloudformation')
    
    def stack_exists(name, required_status = 'CREATE_COMPLETE'):
        try:
            data = client.describe_stacks(StackName = name)
        except ClientError:
            return False
        return data['Stacks'][0]['StackStatus'] == required_status