feat: 変換定義ファイルをyamlに変更。それに伴いステートマシン定義の雛形のプレースホルダーも若干修正

This commit is contained in:
shimoda.m@nds-tyo.co.jp 2022-09-21 00:21:02 +09:00
parent d56c66f96d
commit e850083f1f
4 changed files with 90 additions and 111 deletions

View File

@ -1,24 +0,0 @@
#
# 各項目の第1カラムにリプレース前文字列を記載する
# 各項目の第2カラムstagingの情報を記載する
# 各項目の第3カラムにproductの情報を記載する
# 変換前文字列と変換後文字列をカンマで区切る
#
# AWSアカウントID
{REPLACE_AWS_ACCOUNT_ID},826466435614,826466435614
# 環境情報
{REPLACE_ENV_NAME},staging,product
# サブネット(PrivateSubnet1)
{REPLACE_SUBNET_PRI_1A},subnet-0a47b12f6899ab19e,subnet-0d9bf8cd421cf2489
# サブネット(PrivateSubnet2)
{REPLACE_SUBNET_PRI_1D},subnet-0ecb92c12eb49ebc3,subnet-0595f52cf6fd9b9e7
# セキュリティグループ(ecs-all)
{REPLACE_SG_ECS_ALL},sg-051e0fb9925539592,sg-05df4823fc789b0fa
# セキュリティグループ(ecs-crm-datafetch)
{REPLACE_SG_CRM_DATAFETCH},sg-0b20b7bb1cb1ab886,sg-XXXXXXXXXXXXXXXXX

View File

@ -0,0 +1,32 @@
# 構成
# config: ルートとなる要素
# <ステートマシン名>: ステートマシン定義名
# <環境名>: stagingかproductのみ
# <ステートマシンの雛形内のプレースホルダー名>:置き換え後の値を設定する
config:
r-crm-datafetch-state:
# ステージング環境
staging:
# AWSアカウントID
AWS_ACCOUNT_ID: "826466435614"
# サブネット(PrivateSubnet1)
SUBNET_PRI_1A: subnet-0a47b12f6899ab19e
# サブネット(PrivateSubnet2)
SUBNET_PRI_1D: subnet-0ecb92c12eb49ebc3
# セキュリティグループ(ecs-all)
SG_ECS_ALL: sg-051e0fb9925539592
# セキュリティグループ(ecs-crm-datafetch)
SG_CRM_DATAFETCH: sg-0b20b7bb1cb1ab886
# 本番環境
product:
# AWSアカウントID
AWS_ACCOUNT_ID: "826466435614"
# サブネット(PrivateSubnet1)
SUBNET_PRI_1A: subnet-0d9bf8cd421cf2489
# サブネット(PrivateSubnet2)
SUBNET_PRI_1D: subnet-0595f52cf6fd9b9e7
# セキュリティグループ(ecs-all)
SG_ECS_ALL: sg-05df4823fc789b0fa
# セキュリティグループ(ecs-crm-datafetch)
# TODO: 本番環境のセキュリティグループを作成したら下記のIDを置き換える
SG_CRM_DATAFETCH: sg-XXXXXXXXXXXXXXXXX

View File

@ -1,22 +1,33 @@
import sys
import csv
import os import os
import re import sys
from string import Template
# you need to install module `PyYAML`
import yaml
CONF_FOLDER_PATH = '.' CONF_FOLDER_PATH = '.'
DEFINITION_FOLDER_BASE = '..' DEFINITION_FOLDER_BASE = '..'
CONVERTED_FOLDER_BASE = 'build' CONVERTED_FOLDER_BASE = 'build'
CONVERT_CONF = 'convert.conf' CONVERT_CONF = 'convert_config.yaml'
CHAR_CODE = 'utf-8' CHAR_CODE = 'utf-8'
PRD_NAME = 'product' PRD_NAME = 'product'
STG_NAME = 'staging' STG_NAME = 'staging'
COMMENT_PATTERN = r'(^\s*(#.*|)$)|(^(\s*|)(\r\n|\r|\n)$)'
class StateMachineTemplate(Template):
"""StepFunctionsステートマシンの置き換えるためのテンプレート
生のTemplateクラスはプレースホルダーを表す文字列が`$`ステートマシン定義内で常用する文字と被ってしまうためサブクラス化
"""
# `#{プレースホルダー}`という形式が使えるようになる
delimiter = "#"
def __init__(self, template: str) -> None:
super().__init__(template)
def main(args=None): def main(args=None):
try: try:
""" """
args1: StepFunctionsステート名 args1: StepFunctionsステートマシン
args2: 変換先環境名product or staging args2: 変換先環境名product or staging
""" """
@ -24,17 +35,23 @@ def main(args=None):
os.chdir(os.path.dirname(os.path.abspath(__file__))) os.chdir(os.path.dirname(os.path.abspath(__file__)))
# 引数チェック # 引数チェック
state_name, to_env = check_args(args) state_name, env_name = check_args(args)
print('引数確認OK') print('引数確認OK')
# ファイル存在チェック # ファイル存在チェック
check_file_exist(state_name, to_env) check_file_exist(state_name)
print('ファイル存在確認OK') print('ファイル存在確認OK')
# フォルダがなければ作る
env_name_folder = f'{DEFINITION_FOLDER_BASE}/{state_name}/{CONVERTED_FOLDER_BASE}/{env_name}'
if not os.path.isdir(env_name_folder):
os.makedirs(env_name_folder, exist_ok=True)
print(f'定義生成用フォルダを作成しました。フォルダ名:{env_name_folder}')
# 変換 # 変換
converted_file_name = convert_definition(state_name, to_env) converted_file_name = convert_definition(state_name, env_name)
print(f'変換が完了しました ファイル名:{converted_file_name}') print(f'変換が完了しました ファイル名:{converted_file_name}')
@ -70,50 +87,37 @@ def check_aws_environment(args):
raise Exception('第2引数が不正です') raise Exception('第2引数が不正です')
def check_file_exist(state_name, to_env): def check_file_exist(state_name):
if not os.path.isfile(f'{CONF_FOLDER_PATH}/{CONVERT_CONF}'): if not os.path.isfile(f'{CONF_FOLDER_PATH}/{CONVERT_CONF}'):
raise Exception('変換定義ファイルが存在しません') raise Exception('変換定義ファイルが存在しません')
if not os.path.isfile(f'{DEFINITION_FOLDER_BASE}/{state_name}/{state_name}.json'): if not os.path.isfile(f'{DEFINITION_FOLDER_BASE}/{state_name}/{state_name}.json'):
raise Exception('変換元のステートメント定義が存在しません') raise Exception('変換元のステートマシン定義が存在しません')
if not os.path.isdir(f'{DEFINITION_FOLDER_BASE}/{state_name}/{CONVERTED_FOLDER_BASE}/{to_env}'):
os.makedirs(f'{DEFINITION_FOLDER_BASE}/{state_name}/{CONVERTED_FOLDER_BASE}/{to_env}', exist_ok=True)
return return
def convert_definition(state_name, to_env): def convert_definition(state_name, env_name):
try: try:
# 定義フォルダのパス生成 # 定義フォルダのパス生成
from_folder = f'{DEFINITION_FOLDER_BASE}/{state_name}' from_folder = f'{DEFINITION_FOLDER_BASE}/{state_name}'
to_folder = f'{from_folder}/{CONVERTED_FOLDER_BASE}/{to_env}' to_folder = f'{from_folder}/{CONVERTED_FOLDER_BASE}/{env_name}'
# 変換定義のリスト化 # 変換定義の読み込み
convert_list = set_convert_list() convert_config = read_env_specific_config(state_name, env_name)
# 変換定義のTOの列番号を確認 # テンプレートとなるファイルを読み込み
to_attr_num = set_attribute(to_env, convert_list) with open(f'{from_folder}/{state_name}.json', mode='r', encoding=CHAR_CODE) as from_file:
state_json = from_file.read()
state_json_template = StateMachineTemplate(state_json)
# 環境固有の値を置き換え
substituted_state_json = state_json_template.substitute(ENV_NAME=env_name, **convert_config)
# 読込み、書込みファイルオープン # 書き込みファイルオープン
from_file = open(f'{from_folder}/{state_name}.json', with open(f'{to_folder}/{state_name}.json', mode='w',
mode='r', encoding=CHAR_CODE) encoding=CHAR_CODE, newline='\n') as to_file:
to_file = open(f'{to_folder}/{state_name}.json', mode='w', to_file.write(substituted_state_json)
encoding=CHAR_CODE, newline='\n')
# 変換元ファイルを1行ずつ読込み
for line in from_file:
# 変換定義を1要素ずつ読込み
for convert_value in convert_list:
# 変換
line = line.replace(
convert_value[0], convert_value[to_attr_num])
to_file.write(line)
# 各ファイルクローズ
from_file.close()
to_file.close()
return f'{to_folder}/{state_name}.json' return f'{to_folder}/{state_name}.json'
@ -121,52 +125,19 @@ def convert_definition(state_name, to_env):
raise Exception(f'変換に失敗しました {e}') raise Exception(f'変換に失敗しました {e}')
def set_convert_list(): def read_env_specific_config(state_name, env_name):
try: try:
# 変換定義ファイルオープン # 変換定義ファイルオープン
convert_conf_file = open( with open(f'{CONF_FOLDER_PATH}/{CONVERT_CONF}', mode='r', encoding=CHAR_CODE) as convert_conf_file:
f'{CONF_FOLDER_PATH}/{CONVERT_CONF}', mode='r', encoding=CHAR_CODE) config_yaml = yaml.load(convert_conf_file, yaml.Loader)
# ファイル読込み # 変換定義からステートマシンの環境固有の値を取得
convert_conf = convert_conf_file.readlines() env_specific_config = config_yaml['config'][state_name][env_name]
return env_specific_config
# 変換定義ファイルリスト化
convert_list = []
for row in convert_conf:
if re.match(COMMENT_PATTERN, row[0]):
continue
row = row.rstrip('\n')
data = row.split(',')
convert_list.append(data)
convert_conf_file.close()
return convert_list
except Exception as e: except Exception as e:
Exception('変換定義ファイルのリスト化に失敗しました') Exception('変換定義ファイルの読み込みに失敗しました')
def set_attribute(from_env, convert_list):
"""
変換定義ファイルのどちらの列がどちらの環境かを特定
1列目にどちらかの環境名product or stagingがある場合定義内のその1列が対象の環境となる
"""
to_attr_num = None
for attr in convert_list:
if not attr[1] or not attr[2]:
raise Exception('変換定義が正しくありません')
if attr[1] == from_env:
to_attr_num = 1
elif attr[2] == from_env:
to_attr_num = 2
return to_attr_num
if __name__ == '__main__': if __name__ == '__main__':

View File

@ -7,20 +7,20 @@
"Type": "Pass", "Type": "Pass",
"Parameters": { "Parameters": {
"sns": { "sns": {
"TopicArn": "arn:aws:sns:ap-northeast-1:{REPLACE_AWS_ACCOUNT_ID}:nds-notice-{REPLACE_ENV_NAME}" "TopicArn": "arn:aws:sns:ap-northeast-1:#{AWS_ACCOUNT_ID}:nds-notice-#{ENV_NAME}"
}, },
"ecs": { "ecs": {
"Cluster": "arn:aws:ecs:ap-northeast-1:{REPLACE_AWS_ACCOUNT_ID}:cluster/mbj-newdwh2021-{REPLACE_ENV_NAME}-crm-ecs", "Cluster": "arn:aws:ecs:ap-northeast-1:#{AWS_ACCOUNT_ID}:cluster/mbj-newdwh2021-#{ENV_NAME}-crm-ecs",
"LaunchType": "FARGATE", "LaunchType": "FARGATE",
"NetworkConfiguration": { "NetworkConfiguration": {
"AwsvpcConfiguration": { "AwsvpcConfiguration": {
"Subnets": [ "Subnets": [
"{REPLACE_SUBNET_PRI_1A}", "#{SUBNET_PRI_1A}",
"{REPLACE_SUBNET_PRI_1D}" "#{SUBNET_PRI_1D}"
], ],
"SecurityGroups": [ "SecurityGroups": [
"{REPLACE_SG_ECS_ALL}", "#{SG_ECS_ALL}",
"{REPLACE_SG_CRM_DATAFETCH}" "#{SG_CRM_DATAFETCH}"
], ],
"AssignPublicIp": "DISABLED" "AssignPublicIp": "DISABLED"
} }
@ -37,7 +37,7 @@
"Parameters": { "Parameters": {
"Cluster.$": "$.params.ecs.Cluster", "Cluster.$": "$.params.ecs.Cluster",
"LaunchType.$": "$.params.ecs.LaunchType", "LaunchType.$": "$.params.ecs.LaunchType",
"TaskDefinition": "arn:aws:ecs:ap-northeast-1:{REPLACE_AWS_ACCOUNT_ID}:task-definition/mbj-newdwh2021-{REPLACE_ENV_NAME}-task-crm-datafetch", "TaskDefinition": "arn:aws:ecs:ap-northeast-1:#{AWS_ACCOUNT_ID}:task-definition/mbj-newdwh2021-#{ENV_NAME}-task-crm-datafetch",
"NetworkConfiguration.$": "$.params.ecs.NetworkConfiguration" "NetworkConfiguration.$": "$.params.ecs.NetworkConfiguration"
}, },
"Retry": [ "Retry": [
@ -70,12 +70,12 @@
"Parameters": { "Parameters": {
"Cluster.$": "$.params.ecs.Cluster", "Cluster.$": "$.params.ecs.Cluster",
"LaunchType.$": "$.params.ecs.LaunchType", "LaunchType.$": "$.params.ecs.LaunchType",
"TaskDefinition": "arn:aws:ecs:ap-northeast-1:{REPLACE_AWS_ACCOUNT_ID}:task-definition/mbj-newdwh2021-{REPLACE_ENV_NAME}-task-crm-datafetch", "TaskDefinition": "arn:aws:ecs:ap-northeast-1:#{AWS_ACCOUNT_ID}:task-definition/mbj-newdwh2021-#{ENV_NAME}-task-crm-datafetch",
"NetworkConfiguration.$": "$.params.ecs.NetworkConfiguration", "NetworkConfiguration.$": "$.params.ecs.NetworkConfiguration",
"Overrides": { "Overrides": {
"ContainerOverrides": [ "ContainerOverrides": [
{ {
"Name": "mbj-newdwh2021-{REPLACE_ENV_NAME}-container-crm-datafetch", "Name": "mbj-newdwh2021-#{ENV_NAME}-container-crm-datafetch",
"Environment": [ "Environment": [
{ {
"Name": "OBJECT_INFO_FILENAME", "Name": "OBJECT_INFO_FILENAME",