如何确定 aws cdk 应用程序何时处于部署状态 运行?

How can I identify when the aws cdk app is running in the deployment state?

我有以下问题:

我创建了一个堆栈,在创建了资源之后(特别是带有 Amazon MQ 的 rabbitmq 代理)我想配置一些不能用 cdk 完成而必须通过 REST 完成的东西 api 打电话。

问题是我只想在代理启动并且 运行 和 rabbitmq_url 已解决后仅在部署状态下进行其余 api 调用。

我有类似以下内容,但没有按预期工作:

# Doc Ref: https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-amazonmq-broker.html
rabbitmq_broker = amazonmq. \
    CfnBroker(self, "RabbitMQBroker",
              broker_name=f"{os.getenv('ENVIRONMENT_NAME')}-rabbitmq",
              engine_type="RABBITMQ",
              engine_version="3.8.17",
              deployment_mode="SINGLE_INSTANCE",
              host_instance_type="mq.t3.micro",
              subnet_ids=[[public_subnet.subnet_id for public_subnet in vpc.public_subnets][0]],
              logs=amazonmq.CfnBroker.LogListProperty(general=True),
              # This means we can access rabbitmq from internet without going into the VPC
              publicly_accessible=True,
              users=[amazonmq.CfnBroker.UserProperty(username=os.getenv('RABBITMQ_USER'),
                                                     password=os.getenv('RABBITMQ_PASSWORD'))],
              auto_minor_version_upgrade=True)

rabbitmq_url = f"{rabbitmq_broker.ref}.mq.{os.getenv('CDK_DEFAULT_REGION')}.amazonaws.com"

...

# Only executed when the token is resolved in the deploy stage
if not core.Token.is_unresolved(rabbitmq_broker.ref):
# Create virtual host 'kmhbackend' via RabbitMQ Management HTTP API
    response = requests.post(f"https://{rabbitmq_url}:15671/api/vhosts/kmhbackend",
                          auth=(os.getenv('RABBITMQ_USER'), os.getenv('RABBITMQ_PASSWORD')),
                          headers={'content-type': 'application/json'})

    if response.status_code != requests.codes.get('created'):
        Log.error("Warning: The virtual host has not been created")
        print("Warning: The virtual host has not been created")

如何识别 cdk 应用程序何时 运行 处于部署状态?

我不想只使用上下文变量来识别它。

提前致谢

所以在深入阅读文档后,解决方案是在一个新的嵌套堆栈中创建一个自定义资源,并在两个堆栈之间添加依赖关系,因此自定义资源将等待初始资源完全部署。

所以解决方法是这样的:

class MessageBrokerConfigStack(core.NestedStack):
    """
    This stack will take of configure rabbitmq once it's created by API calls

    * the RabbitMQ Management HTTP API at 'rabbitmq-web-console:15671' ,
    docs of API can be found in rabbitmq_url/api/index.html

    Warning: In the docs the port used for the RabbitMQ Management HTTP API is 15672,
    but with AWS the port to be used is 15671
    """

    def __init__(self, scope: core.Construct, id: str,
                 vpc: ec2.Vpc, rabbit_broker_url: str,
                 rabbitmq_user: str, rabbitmq_password: str,
                 **kwargs) -> None:
        super().__init__(scope, id, **kwargs)
    
        ...
        onEvent = lambda_. \
        Function(self, "CR_RabbitMQ_configurator_handler",
                 function_name="cr_cdk_rabbitmq_configurator_handler",
                 description="Function that will handle all the configuration for rabbitmq broker created by cdk",
                 runtime=lambda_.Runtime.PYTHON_3_7,
                 layers=[layer],
                 handler="config_rabbitmq.lambda_handler",
                 code=lambda_.Code.from_asset('aws_lambda/lambdas')
                 )

    config_rabbitmq_provider = cr.Provider(self, 'CR_RabbitMQ_configurator_provider',
                                           vpc=vpc,
                                           vpc_subnets=ec2.SubnetSelection(subnet_type=ec2.SubnetType.PRIVATE),
                                           on_event_handler=onEvent)

    # Will create a custom resource in cloudformation, this custom resource is compose by a lambda that
    # will contain a function and this function will handle the different events
    # ref https://docs.aws.amazon.com/cdk/latest/guide/apps.html#lifecycle
    # ref https://docs.aws.amazon.com/cdk/latest/guide/cfn_layer.html#cfn_layer_custom
    config_rabbitmq = core.CustomResource(self, 'CR_RabbitMQ_configurator',
                                          service_token=config_rabbitmq_provider.service_token,
                                          properties={
                                              "rabbitmq_url": rabbit_broker_url,
                                              "rabbit_user": rabbitmq_user,
                                              "rabbit_password": rabbitmq_password
                                          })

然后 lambda 代码将侦听事件并执行所需的操作。

import requests


def lambda_handler(event, context):
    """
    This method is the native input for AWS Lambda
    """

    print("lambda rabbitmq received")
    print(event)
    print(context)

    props = event['ResourceProperties']
    rabbitmq_url = props['rabbitmq_url']
    rabbit_user = props['rabbit_user']
    rabbit_password = props['rabbit_password']

    print(rabbitmq_url)
    print(rabbit_user)
    print(rabbit_password)

    if event["RequestType"] == "Create":
        # ref https://docs.aws.amazon.com/cdk/latest/guide/apps.html#lifecycle
        # ref https://docs.aws.amazon.com/cdk/latest/guide/cfn_layer.html#cfn_layer_custom
        # Only executed when the token is resolved in the deploy stage
        # Create virtual host 'kmhbackend' via RabbitMQ Management HTTP API
        response = requests.put(f"https://{rabbitmq_url}:15671/api/vhosts/new_virtual_host",
                                auth=(rabbit_user, rabbit_password),
                                headers={'content-type': 'application/json'})

        print("response from rabbitmq:")
        print(response)

        if response.status_code != requests.codes.get('created'):
            print("Warning: The virtual host has not been created")
    

然后在父栈上我们只需要做

resource = Resource(....)

configResource = ConfigResouce(...)

configResource.add_dependency(resource)