いちはじCDK第7回 また見直し

ふっと気が付いたこと

ちょっと調べる用事があって、S3のConstructのIF仕様書を見ていてフッと気が付いたことが1つあります。

accelerate_configuration (Union[IResolvable, AccelerateConfigurationProperty, Dict[str, Any], None])

赤字の部分ですが、最初は良く考えず読み飛ばしてましたけど!
「あれ?」って思いました、これは??パラメータdict型で渡せばよいのでは?!
(´・ω・)えっマジで!
今までさんざんIFデータ構成を作ってきましたけどっ!不要では?
って思っちゃいました…
(´・ω・)えっ?どういうこと?
pythonは、dict型でパラメータ渡せるので、Constructのパラメータ形式を合わせればそのまま渡せるように設計されているのでは?と思ったわけです。
(´・ω・)おお…Construct設計した人は頭ええね…
ということで、今までことを一旦忘れて改善してみようかなと…
(・´з`・)何回変えたら気が済むんだよ・・・
・・・まぁまぁ・・・

プロジェクトの変更点

とりあえず、IFデータ構成が不要になるので、myec2.pyが不要になります。
(´・ω・)今までの苦労は一体・・・

cdk_core_project/
├ .venv/
│ └…省略…
├ core/
│ ├ basetypes
│ │ ├ __init__.py 
│ │ ├ mycommon.py
│ │ └ myec2.py★削除
│ ├ myconstructs
│ │ ├ mybase.py
│ │ ├ myctrl.py
│ │ ├ myec2.py
│ │ ├ __init__.py
│ │ └ mytags.py
│ ├ parameters
│ │ └ first_vpc_params.yaml 
│ ├ utils
│ │ ├ __init__.py 
│ │ ├ configread.py
│ │ └ reprice.py
│ ├ __init__.py
│ └ first_vpc_stack.py
├ tests/
│ ├unit/
│ │├ __init__.py
│ │└ test_cdk_core_project_stack.py
│ └ __init__.py
├ .gitignore
├ app.py
├ cdk.json
├ README.md
├ requirements.txt
├ requirements-dev.txt
└ source.bat

パラメータリストの見直し

なんでそうしたんだろう…って思いますけど、Consructの最初の2つパラメータは決まっています。

scope (Construct)
id (str)

で「なんでそうしたんだろう」ってのはパラメータリストの最初を以下のように「construct_id」ってしちゃったんですよね…

…省略…
firstvpc:
  vpcs:
    first_vpc:
      construct_id: "firstvpc"
      cidr_block: "10.0.0.0/16"
…省略…

この部分を全部”construct_id“→”id“に変更になりますね。
dict型で渡すのに違うパラメータ名だと渡せないので…
あとtagのところ、Constructにそのまま渡すには以下のように変更になります。
ここはちょっと可読性落ちたかなって気がしますけど…他の部分でメリットが大きいので我慢…

firstvpc:
  vpcs:
    first_vpc:
      cnstruct_id: "firstvpc"
      cidr_block: "10.0.0.0/16"
      enable_dns_hostnames: True
      enable_dns_support: True
      instance_tenancy: "default"
      tags:
        Name: "first-vpc"

firstvpc:
  vpcs:
    first_vpc:
      id: "firstvpc"
      cidr_block: "10.0.0.0/16"
      enable_dns_hostnames: True
      enable_dns_support: True
      instance_tenancy: "default"
      tags:
        - key: "Name"
          value: "first-vpc"

MyCtrlクラス

第5回の見直しと改善で作ったクラスですね。
変更点は、
「よくよく考えてみると共通的に追加するタグを定義してたけど使ってなかった」
…ので使おうかなって部分です。共通タグって言うのは、パラメータリスト「common」に定義されている以下の赤字部分です。

first_vpc_params.yaml
---
common:
  region: ap-northeast-1
  account : "123456789099"
  tags :
    commontag1: "commontags-value1"
    commontag2: "commontags-value2"

これを各Constructに共通的に付与するためのメンバ関数をMyCtrlクラスに追加しました。(赤字

from typing import Any

from aws_cdk import Stack, Tags

from core.basetypes.mycommon import MyCommonIF
from core.myconstructs.mybase import MyBase
from core.utils.reprice import rep_rice


class MyCtrl:
    def __init__(self, config: dict):
        self.config: dict = config
        self.common = MyCommonIF(**config["common"])

~ 省略 ~

    def add_common_tags(self, stack: Stack):
        if self.common.tags is not None:
            for key,value in self.common.tags.items():
                Tags.of(stack).add(key=key,value=value)

MyBaseクラス

ここは前後で記載します。赤字を追加&変更してます。
大きな変更はcreate関数が仮想関数から普通メンバ関数になったことですね。
各Constructのラッパークラス(次項)で定義していた部分が今回の変更で同じ形になるのでMyBaseクラスにまとめています。
create関数で実施しているのはConstructの先頭パラメータであるscopeを作って、渡されるその他のパラメータ(dict型)と統合して、ConstructのIFとして渡す作業をしてます。

from typing import Any




class MyBase:
    def __init__(self, obj: Any, name: str):
        self.obj = obj
        self.name = name
        self.myif = {}

    def create(self) -> Any:
        pass








    def get_name(self) -> str:
        return self.name

from typing import Any

from constructs import Construct


class MyBase:
    def __init__(self, construct: Construct, name: str):
        self.construct = construct
        self.name = name
        self.myif = {}

    def create(self, myif: dict) -> Any:
        tmpdict: dict ={"scope": self.construct}
        tmpif: dict = {**tmpdict,**myif}
        self.myif = myif
        return self._rsc_(rscif=tmpif, myif=self.myif)

    def _rsc_(self, rscif: dict, myif: dict) -> Any:
        pass

    def get_name(self) -> str:
        return self.name

各Constructのラッパークラス

myec2.pyの各ラッパークラスですね。ここは大きく変わりますCfnVpcを例に前後で記載します。
不要な部分が結構あるのでその辺をゴッソリ削除します。

まずはcreate関数の変更ですね。ここは各Constructのラッパークラス毎に定義してたんですが、形が同じになったのでMyBaseクラスへ実装処理をまとめてます。

また、注意点としては、パラメータリストをdict型で渡す場合、ほとんどの場合が文字か数字かbool型になるので、yamlファイルにパラメータとして定義したものをそのまま渡すことができるのですが、一部オブジェクト型となるパラメータもあり、そういったケースではyamlファイルにパラメータとして定義したものをそのまま渡すことができないです。例としてはpythonのdateとかが該当しますね。

…で!そういったケースは、yamlファイルにオブジェクトが書けないので一旦(date型を例に)「YYYY-MM-DD hh:mm:ss」のように記載しておいて、このcreate関数のところで、「YYYY-MM-DD hh:mm:ss」→date型に変換して、dictパラメータを更新するような補正をする必要が出てきます。

MyBaseクラスへ実装処理をまとめものの、そういったケースに対処するため、各Constructのラッパークラスにcreate関数を残しました。(ただ、あまり使うケースはないです)

残りの変更点は、Constructのパラメータを一つづつ項目転送していた部分です。
ここはゴッソリ不要になるので削除してます。

myec2.py
# ==============================
# CfnVPC
# ==============================
class MyVpc(MyBase):
    def __init__(self, obj: Any, name: str):
        super().__init__(obj, name)

    def create(self, myif: dict) -> Any:
        self.myif = myif
        return self._vpc_(myif=MyVPCIF(**myif), updif=self.myif)

    def _vpc_(self, myif: MyVPCIF, updif: dict) -> CfnVPC:
        tags = MyTags(myif.tags)
        rsc = CfnVPC(★以下のパラメータ透過設定が不要になる
            self.obj,
            myif.construct_id,
            cidr_block=myif.cidr_block,
            enable_dns_hostnames=myif.enable_dns_hostnames,
            enable_dns_support=myif.enable_dns_support,
            instance_tenancy=myif.instance_tenancy,
            ipv4_ipam_pool_id=myif.ipv4_ipam_pool_id,
            ipv4_netmask_length=myif.ipv4_netmask_length,
            tags=tags,
        )
        # vpc_id
        updif["vpc_id"] = rsc.attr_vpc_id
        return rsc

myec2.py
# ==============================
# CfnVPC
# ==============================
class MyVpc(MyBase):
    def __init__(self, obj: Any, name: str):
        super().__init__(obj, name)

    def create(self, myif: dict) -> Any:
        # もしmyifの内容を補正する必要があるならここで!
        return super().create(myif)


    def _rsc_(self, rscif: dict, myif: dict) -> CfnVPC:
        rsc = CfnVPC(**rscif)





     ★きれいになくなる!





        # vpc_id
        myif["vpc_id"] = rsc.attr_vpc_id
        return rsc

スタック処理

first_vpc_stack.pyに関する変更点ですね。
実はあまり変更はなくて、以下の部分の追加のみになります。(赤字
共通的なタグを追加しているところですね。こうしておくとすべてのConstructに等しくパラメータリストのcommonに定義したタグが追加されます。

from aws_cdk import Stack
from constructs import Construct
~省略~
class FirstVpcStack(Stack):
    def __init__(
        self, scope: Construct, construct_id: str, myctrl: MyCtrl, **kwargs
    ) -> None:
        super().__init__(scope, construct_id, **kwargs)
        self.myctrl = myctrl
        myctrl.add_common_tags(self)
        # VPC
        firstvpc = myctrl.create(MyVpc(obj=self, name="firstvpc.vpcs.first_vpc"))
~省略~

これで見直し終了です。
色々書かなくて良い部分が増えてスッキリできたと思っています。
今回のGITはこちらを参照して下さい。
次はいよいよEC2を作ってみようと思います。
「作成中」良かったら見てみて下さい。

コメント

タイトルとURLをコピーしました