CDK(Python)のv2移行を対応しました

#AWS
#CDK
#Python
#CDKv2

CDKをv1からv2へ移行することになり、体験した手順を残しておこうと思います

v2移行の記事は他にいくらでもあると思いますが、これからv2移行する方に少しでも参考になればと思います

 

以下記事では前準備のCodePipelineの移行をしています

CDK v1では使用するリソースごとにライブラリを個別でインストールする必要がありますが、v2になるとaws-cdk-libにまとめられるのでこれだけインストールすればよくなります(experimentalのものは_alphaのライブラリを別途インストールする必要があり)

 

aws-cdk.core.Constructsはconstructs.Constructに別ライブラリになったようです

aws-cdk.core aws-cdk.aws-codepipeline aws-cdk.aws-codepipeline-actions aws-cdk.aws-codecommit aws-cdk.pipelines aws_cdk.aws_events aws-cdk.aws_codestarnotifications aws-cdk.aws_sns aws_cdk.aws_dynamodb aws_cdk.aws_lambda_event_sources aws_cdk.aws_events_targets aws-cdk.aws_ssm aws-cdk.aws_appsync aws-cdk.aws_cognito aws-cdk.aws_wafregional aws-cdk.aws_codebuild aws_cdk.aws_stepfunctions_tasks aws_cdk.aws_cloudwatch_actions
aws-cdk-lib constructs
$ pip install -r requirements.txt

・v1

from aws_cdk import ( core, aws_events as events, aws_iam as iam, aws_kms as kms, aws_dynamodb as dynamodb, aws_lambda as lambda_, aws_lambda_event_sources as event_source, aws_logs as logs, aws_ssm as ssm, aws_cloudwatch as cloudwatch, aws_cloudwatch_actions as cw_actions, aws_sns as sns, ) class SampleStack(core.Stack): def __init__(self, scope: core.Construct, id: str, **kwargs) -> None: super().__init__(scope, id, **kwargs)

・v2

from aws_cdk import ( Stack, aws_events as events, aws_iam as iam, aws_kms as kms, aws_dynamodb as dynamodb, aws_lambda as lambda_, aws_lambda_event_sources as event_source, aws_logs as logs, aws_ssm as ssm, aws_cloudwatch as cloudwatch, aws_cloudwatch_actions as cw_actions, aws_sns as sns, ) from constructs import Construct class SampleStack(Stack): def __init__(self, scope: Construct, id: str, **kwargs) -> None: super().__init__(scope, id, **kwargs)

また、

RemovalPolicy,AssetHashType,BundlingOptions,

DockerVolume,Duration

などはcoreからでなくaws_cdkからとれるようになります

alias設定が非推奨になっていました

 

・v1

lambda_funcion_alias = lambda_funcion.current_version.add_alias('live')

・v2

from aws_cdk import ( aws_lambda as lambda_ ) lambda_function_alias = lambda_.Alias(self, 'LambdaAliasLive', alias_name='Live', version=lambda_function.current_version )

IRoleでadd_to_policyが使えなくなっていました 代わりにadd_to_principal_policyを使用  

・v1

pre_sign_up_func_role = iam.Role.from_role_arn( self, 'preSignUpFuncRole', pre_sign_up_func.role.role_arn) pre_sign_up_func_role.add_to_policy(statement=iam.PolicyStatement( actions=['cognito-idp:*'], resources=[cognitouserpool.attr_arn]))

・v2

pre_sign_up_func_role = iam.Role.from_role_arn( self, 'preSignUpFuncRole', pre_sign_up_func.role.role_arn) pre_sign_up_func_role.add_to_principal_policy(statement=iam.PolicyStatement( actions=['cognito-idp:*'], resources=[cognitouserpool.attr_arn]))

L2(Cfnつかないやつ)がv2ではexperimentalだったのでstableのL1に変更

 

・L2

from aws_cdk import ( core, aws_iam as iam, aws_appsync as appsync, aws_cognito as awscognito ) import os dirname = os.path.dirname(__file__) class AppSyncStack(core.Stack): def __init__(self, scope: core.Construct, construct_id: str, **kwargs) -> None: user = kwargs['user'] del kwargs['user'] super().__init__(scope, construct_id, **kwargs) user_pool = awscognito.UserPool.from_user_pool_id( self, "UserPool", user.pool_id) graphQLApi = appsync.GraphqlApi(self, "graphqlapi", name="BFF", schema=appsync.Schema.from_asset( os.path.join(dirname, "schema.graphql")), authorization_config=appsync.AuthorizationConfig( default_authorization=appsync.AuthorizationMode( authorization_type=appsync.AuthorizationType.USER_POOL, user_pool_config=appsync.UserPoolConfig( user_pool=user_pool ) ) ), xray_enabled=True) core.CfnOutput(self, "AwsAppsyncGraphqlEndpoint", value=graphQLApi.graphql_url)

 

・L1

from aws_cdk import ( Stack, CfnOutput, aws_iam as iam, aws_appsync as appsync ) from constructs import Construct import os dirname = os.path.dirname(__file__) with open(os.path.join(dirname, "schema.graphql"), 'r') as file: data_schema = file.read().replace('\n', '') class AppSyncStack(Stack): def __init__(self, scope: Construct, construct_id: str, **kwargs) -> None: user = kwargs['user'] del kwargs['user'] super().__init__(scope, construct_id, **kwargs) graphQLApi = appsync.CfnGraphQLApi(self, "graphqlapi", name="BFF", authentication_type="AMAZON_COGNITO_USER_POOLS", user_pool_config=appsync.CfnGraphQLApi.UserPoolConfigProperty( user_pool_id=user.pool_id ), xray_enabled=True ) appsync.CfnGraphQLSchema(self, "graphqlschema", api_id=graphQLApi.attr_api_id, definition=data_schema ) CfnOutput(self, "AwsAppsyncGraphqlEndpoint", value=graphQLApi.attr_graph_ql_url) self.graphQLApi = graphQLApi

CfnGraphQLSchemaのdefinitionに指定しているファイル(schema.graphql)にはコメントアウト等が含まれていると失敗してしまいました

・L2

field_options = [ { "field_name": "sample1", "type_name": "Query", "lambda_alias": board.list_board_func_alias }, { "field_name": "sample2", "type_name": "Mutation", "lambda_alias": board.post_comment_func_alias } ] for option in field_options: graphQLApi.add_lambda_data_source( f'{option["field_name"]}DS', lambda_function=option["lambda_alias"] ).create_resolver( field_name=option["field_name"], type_name=option["type_name"] )

・L1

field_options = [ { "field_name": "sample1", "type_name": "Query", "lambda_alias": board.list_board_func_alias }, { "field_name": "sample2", "type_name": "Mutation", "lambda_alias": board.post_comment_func_alias } ] for option in field_options: data_source = appsync.CfnDataSource(self, f'{option["field_name"]}DS', api_id=graphql.graphQLApi.attr_api_id, name=f'{option["field_name"]}DS', type="AWS_LAMBDA", lambda_config=appsync.CfnDataSource.LambdaConfigProperty( lambda_function_arn=option["lambda_alias"].function_arn), service_role_arn=graphql.appsync_role.role_arn ) resolver = appsync.CfnResolver(self, f'{option["field_name"]}RS', api_id=graphql.graphQLApi.attr_api_id, field_name=option["field_name"], type_name=option["type_name"], data_source_name=data_source.name, ) resolver.add_depends_on(data_source)

L1の場合、add_depends_onでdata_sourceとの依存関係をつけないと失敗しました

CloudFrontWebDistributionのalias_configurationがviewer_certificateとなったようです

 

・v1

cloudfront.CloudFrontWebDistribution(self, 'webdistribution', origin_configs=[..省略], alias_configuration=cloudfront.AliasConfiguration( acm_cert_ref=acm_arn, names=[ domain_name ], security_policy=cloudfront.SecurityPolicyProtocol.TLS_V1_2_2019 ), logging_config=cloudfront.LoggingConfiguration( bucket=accessLogsBucket, prefix="CloudFront" ), price_class=cloudfront.PriceClass.PRICE_CLASS_200, error_configurations=[..省略] )

 

・v2

cert = certificatemanager.Certificate.from_certificate_arn(self, "certificate", acm_arn) cloudfront.CloudFrontWebDistribution(self, 'webdistribution', origin_configs=[..省略], viewer_certificate=cloudfront.ViewerCertificate.from_acm_certificate( certificate=cert, aliases=[domain_name], security_policy=cloudfront.SecurityPolicyProtocol.TLS_V1_2_2021 ), logging_config=cloudfront.LoggingConfiguration( bucket=accessLogsBucket, prefix="CloudFront" ), price_class=cloudfront.PriceClass.PRICE_CLASS_200, error_configurations=[..省略] )

v1

sample_task = sfn.Task(self, "SampleTask", task=sfn_tasks.InvokeFunction( sample_task_func), input_path="$" ) sample_map = sfn.Map(self, "SampleMap", input_path="$", items_path="$.samples", result_path="$.SampleResult", output_path="$" ) sample_map.iterator( before_sample_task.add_retry(max_attempts=2) ).next(sample_task.add_retry(max_attempts=2))

v2

sample_task = sfn_tasks.LambdaInvoke(self, "SampleTask", lambda_function=sample_task_func, input_path=sfn.JsonPath.string_at( "$.Payload") ) sample_map = sfn.Map(self, "SampleMap", input_path=sfn.JsonPath.string_at( "$.Payload"), items_path=sfn.JsonPath.string_at( "$.samples"), result_path=sfn.JsonPath.string_at( "$.SampleResult") ) sample_map.iterator( before_sample_task.add_retry(max_attempts=2) ).next(sample_task.add_retry(max_attempts=2))

aws_stepfunctions.Taskが非推奨になっていたので、aws_stepfunctions_tasks.LambdaInvokeに変更

〇〇_pathで指定する「"$"」などの文字列は「aws_stepfunctions.JsonPath.string_at()」で囲む

 

また、LambdaInvokeからoutputされる返り値は以下のように"Payload"の中に入って伝わるようになったみたいなので

「$ -> $.Payload」のように変更する必要がありました

"input": { "ExecutedVersion": "7", "Payload": { "samples": [ { "sample_id": "2ME2022" } ] } }