本記事は オルトプラス Advent Calendar 2023 の12/05の記事です。
はじめに
どうも!!オルトプラスの浦谷(urachooooooo)です
所属は技術部SREでテックスペシャリストとして横断的にデータベースを見ています!!
肩書きはエンジニアマネージャーですが生粋のDBAです!!
本記事ではPythonについて書いていきます。
それでは5日目のアドベントカレンダー開始しますー!!
概要
アジェンダとしては「PythonでTOMLを使うための仕組み」についてです。
こちらについてはサンプルスクリプトを使用して解説していきます。
詳細
オルトプラスに入社してからPythonを使用して色々と自動化したりツールを作成したりしているのですが、自分はPythonのコンフィグファイルにTOMLを使用することにしました!!
まずはじめにやったこととして「TOMLを読むための共通モジュールを作る」です。
この共通モジュールを使用することで以降作成するツールで使用することが可能です(楽したいですし💦)
TOMLを使用するためのシンプルなスクリプトを使用して解説していきます!!
その前にTOMLについて
TOMLは「Tom's Obvious Minimal Language」の略で、TOMLは設定ファイルのフォーマットの1つです。
TOMLのサイトでは下記の様に記載されています。
- 人間用の設定ファイル形式(A config file format for humans.)
- トムの明瞭で最小の言語(Tom's Obvious, Minimal Language.)
簡単に説明するとTOMLは
可読性が高く、様々なネイティブ型(Key/Value PairsやArrays)があり、様々な言語(PHPやPython)に対応しています
ソースコードについて
サンプルの「ソースコード構成」及び、「ソースコード内容」についてこちらに記載していきます。
ソースコード構成
「toml-config-display」はTOMLを実行するためのプロジェクト(ROOT)です。
下記の構成通りにサンプルスクリプトを配置することで今回説明する内容を再現することができます
-
├── tcd_setup.py │ └── toml-config-display ├── config │ ├── common.toml │ ├── tcd_general.toml │ └── tcd_tidb.toml ├── requirements.txt └── tomlcd ├── __init__.py ├── __main__.py ├── display_general_toml.py ├── display_tidb_toml.py └── libs ├── __init__.py ├── display_toolkit.py ├── tcd_config.py └── toml_toolkit.py
ソースコード内容
セットアップスクリプトは「tcd_setup.py」と「requirements.txt」になります
-
tcd_setup.py
- 実行すると「ソースコード構成」と同じファイルを生成します
- 生成するファイルは空ファイルになります
-
requirements.txt
- 実行環境構築(pipインストール)時に使用します
setup
tcd_setup_py
-
tcd_setup.py
#!/usr/bin/env python3 # -*- coding: utf-8 -*- """ GLOBAL変数初期化 """ # ライブラリインポート import os # OS import sys # SYS import textwrap # ヒアドキュメント import inspect # ファンクション名取得 import pathlib # touch # コンスタント TCD_BASE_PATH = os.path.abspath(".") TCD_PROJECT_PATH = os.path.join(TCD_BASE_PATH, "toml-config-display") TCD_CONFIG_PATH = os.path.join(TCD_PROJECT_PATH, "config") TCD_TOMLCD_PATH = os.path.join(TCD_PROJECT_PATH, "tomlcd") TCD_LIBS_PATH = os.path.join(TCD_TOMLCD_PATH, "libs") """ tcd_setup.py -------------------------------------------------------- toml-config-display(tcd)環境セットアップモジュール """ def f_mkdir(in_args_dir_info): try: f_display_division("mkdir", "start") for dir_info in in_args_dir_info: print(dir_info) os.makedirs(dir_info, exist_ok=True) f_display_division("mkdir", "end") return True except: function_name = inspect.currentframe().f_code.co_name error_type, error_value, error_stacktrace = sys.exc_info() f_display_error(function_name, error_type, error_value, error_stacktrace) return False def f_file_touch(in_args_file_info): try: f_display_division("touch", "start") for file_fullpath in in_args_file_info: print(file_fullpath) file_info = pathlib.Path(file_fullpath) file_info.touch() f_display_division("touch", "end") return True except: function_name = inspect.currentframe().f_code.co_name error_type, error_value, error_stacktrace = sys.exc_info() f_display_error(function_name, error_type, error_value, error_stacktrace) return False def f_execute_confirmation(in_execute_message): # メッセージ設定 enter_support_message = textwrap.dedent(''' {execute_message} Please enter 'yes' or 'no' [y/N]: ''').format(execute_message=in_execute_message).strip() try: while True: choice = input(enter_support_message).lower() if choice in ["y", "yes"]: return True elif choice in ["n", "no"]: return False except: function_name = inspect.currentframe().f_code.co_name error_type, error_value, error_stacktrace = sys.exc_info() f_display_error(function_name, error_type, error_value, error_stacktrace) return False def f_display_division(in_action_type, in_division_type): if in_division_type == "start": start_message = textwrap.dedent(''' [{action_type}] +---------------------------------------------------------------------------------+ ''').format(action_type=in_action_type).strip() print(start_message) elif in_division_type == "end": end_message = textwrap.dedent(''' +---------------------------------------------------------------------------------+ ''').strip() print("{} {}".format(end_message, "\n")) def f_display_error(in_function_name, in_error_type, in_error_value, in_error_stacktrace): # エラー情報設定 error_message = textwrap.dedent(''' [{function_name}] +---------------------------------------------------------------------------------+ error_type : {error_type} error_value : {error_value} error_stacktrace : {error_stacktrace} +---------------------------------------------------------------------------------+ ''').format(function_name=in_function_name, error_type=in_error_type, error_value=in_error_value, error_stacktrace=in_error_stacktrace).strip() # エラー情報表示 print("{} {}".format(error_message, "\n")) def f_display_finish_message(in_message): # メッセージ設定 finish_message = textwrap.dedent(''' ☆ ☆ ☆ ☆ ☆ ☆ ☆ ☆ ☆ ☆ ☆ ☆ ☆ ☆ ☆ ☆ ☆ ☆ ☆ ☆ ☆ ☆ ☆ ☆ ☆ ☆ ☆ ☆ ☆ ☆ ☆ ☆ ☆ ☆ ☆ ☆ ☆ ☆ ☆ ☆ ☆ ☆ ☆ ☆ {message} have been completed !!! ☆ ☆ ☆ ☆ ☆ ☆ ☆ ☆ ☆ ☆ ☆ ☆ ☆ ☆ ☆ ☆ ☆ ☆ ☆ ☆ ☆ ☆ ☆ ☆ ☆ ☆ ☆ ☆ ☆ ☆ ☆ ☆ ☆ ☆ ☆ ☆ ☆ ☆ ☆ ☆ ☆ ☆ ☆ ☆ ''').format(message=in_message) print("{}".format(finish_message, "\n")) def f_create_template(): ######################## # ディレクトリ作成 ######################## args_dir_info = [] args_dir_info.extend([TCD_CONFIG_PATH, TCD_LIBS_PATH]) """ f_mkdir """ result = f_mkdir(args_dir_info) if result == True: ######################## # 空ファイル作成 ######################## args_file_info = [] args_file_info.extend([os.path.join(TCD_CONFIG_PATH, "common.toml"), os.path.join(TCD_CONFIG_PATH, "tcd_general.toml"), os.path.join(TCD_CONFIG_PATH, "tcd_tidb.toml"), os.path.join(TCD_TOMLCD_PATH, "__init__.py"), os.path.join(TCD_TOMLCD_PATH, "__main__.py"), os.path.join(TCD_TOMLCD_PATH, "display_general_toml.py"), os.path.join(TCD_TOMLCD_PATH, "display_tidb_toml.py"), os.path.join(TCD_LIBS_PATH, "__init__.py"), os.path.join(TCD_LIBS_PATH, "display_toolkit.py"), os.path.join(TCD_LIBS_PATH, "tcd_config.py"), os.path.join(TCD_LIBS_PATH, "toml_toolkit.py"), os.path.join(TCD_PROJECT_PATH, "requirements.txt")]) """ f_file_touch """ result = f_file_touch(args_file_info) if result == True: """ f_display_finish_message """ f_display_finish_message("{}".format("tcd_setup")) def f_main(): tcd_setup_message = textwrap.dedent(''' +---------------------------------------------------------------------------------+ スクリプト実行パス「{tcd_base_path}」配下に TOML動作確認用の環境を構築します よろしいでしょうか? ※パーミッションが有効でない場合はエラーになります +---------------------------------------------------------------------------------+ ''').format(tcd_base_path=TCD_BASE_PATH).strip() result = f_execute_confirmation(tcd_setup_message) if result == True: """ f_create_template """ f_create_template() """ main """ if __name__ == '__main__': f_main()
requirements_txt
-
requirements.txt
toml==0.10.2
config
TOMLフォーマットの設定ファイルです
-
common.toml
- 便宜上分けています(今回のプロジェクト以外でも使用可能なパラメータのため)
- 表示では使用しません(判定で使用)
-
tcd_general.toml
- Key-Valueの最もシンプルな構成
- このTOMLの内容を表示します
-
tcd_tidb.toml
- TiDBの「Server recommendations」をベースとした階層と配列を含んだ構成
- このTOMLの内容を表示します
TOMLの記述について
- テーブル(TABLE)
- パラメータのカテゴリーとして分けている「[]」で囲われている値は「テーブル」と呼ばれています
- 例えば「common.toml」の「[environment_info]」はテーブルであり、「tcd_general.toml」の「[setup_info]」もテーブルです
- 例えば「common.toml」の「[environment_info]」はテーブルであり、「tcd_general.toml」の「[setup_info]」もテーブルです
- パラメータのカテゴリーとして分けている「[]」で囲われている値は「テーブル」と呼ばれています
- キー(KEY)
- 値を検索するためのキー
- 例えば「common.toml」の「ENVIRONMENT_LIST」はキーであり、「tcd_general.toml」の「TCD_ROOT_DIR」や「TCD_CONFIG_DIR」もキーです
- 例えば「common.toml」の「ENVIRONMENT_LIST」はキーであり、「tcd_general.toml」の「TCD_ROOT_DIR」や「TCD_CONFIG_DIR」もキーです
- 値を検索するためのキー
- 値(VALUE)
- キーに対する値
- 例えば、「common.toml」の「['development', 'production']」は値で、「tcd_general.toml」の「"toml-config-display"」や「"config"」も値です
- キーに対する値
common_toml
-
common.toml
[environment_info] ENVIRONMENT_LIST = ['development', 'production']
tcd_general_toml
-
tcd_general.toml
[setup_info] TCD_ROOT_DIR = "toml-config-display" TCD_CONFIG_DIR = "config" TCD_SCRIPT_DIR = "tomlcd" TCD_LIBS_DIR = "libs" [config_info] TCD_GENERAL_TOML = "tcd_general.toml" TCD_TIDB_TOML = "tcd_tidb.toml" [libs_info] TCD_CONFIG_PY = "tcd_config.py" TOML_TOOLKIT_PY = "toml_toolkit.py" DISPLAY_TOOLKIT_PY = "display_toolkit.py" [script_info] DISPLAY_GENERAL_TOML_PY = "display_general_toml.py" DISPLAY_TIDB_TOML_PY = "display_tidb_toml.py"
tcd_tidb_toml
-
tcd_tidb.toml
[development] [development.tidb_cluster] INSTANCE_TYPE = "t4g.2xlarge" RESOURCE.CPU = "8 core+" RESOURCE.MEMORY = "16 GB+" RESOURCE.STORAGE = "No special requirements" RESOURCE.NETWORK = "Gigabit network card" RESOURCE.MINIMUM_REQUIREMENT = 1 SERVER_LIST = [ "tidb-server-01" ] [development.pd_cluster] INSTANCE_TYPE = "t4g.xlarge" RESOURCE.CPU = "4 core+" RESOURCE.MEMORY = "8 GB+" RESOURCE.STORAGE = "SAS, 200 GB+" RESOURCE.NETWORK = "Gigabit network card" RESOURCE.MINIMUM_REQUIREMENT = 1 SERVER_LIST = [ "pd-server-01" ] [development.tikv_cluster] INSTANCE_TYPE = "i4g.2xlarge" RESOURCE.CPU = "8 core+" RESOURCE.MEMORY = "32 GB+" RESOURCE.STORAGE = "SAS, 200 GB+" RESOURCE.NETWORK = "Gigabit network card" RESOURCE.MINIMUM_REQUIREMENT = 3 SERVER_LIST = [ "tikv-server-01", "tikv-server-02", "tikv-server-03" ] [production] [production.tidb_cluster] INSTANCE_TYPE = "Im4gn.4xlarge" RESOURCE.CPU = "16 core+" RESOURCE.MEMORY = "48 GB+" RESOURCE.STORAGE = "SSD" RESOURCE.NETWORK = "10 Gigabit network card (2 preferred)" RESOURCE.MINIMUM_REQUIREMENT = 2 SERVER_LIST = [ "tidb-server-01", "tidb-server-02" ] [production.pd_cluster] INSTANCE_TYPE = "Im4gn.2xlarge" RESOURCE.CPU = "8 core+" RESOURCE.MEMORY = "16 GB+" RESOURCE.STORAGE = "SSD" RESOURCE.NETWORK = "10 Gigabit network card (2 preferred)" RESOURCE.MINIMUM_REQUIREMENT = 3 SERVER_LIST = [ "pd-server-01", "pd-server-02", "pd-server-03" ] [production.tikv_cluster] INSTANCE_TYPE = "i4g.4xlarge" RESOURCE.CPU = "16 core+" RESOURCE.MEMORY = "64 GB+" RESOURCE.STORAGE = "SSD" RESOURCE.NETWORK = "10 Gigabit network card (2 preferred)" RESOURCE.MINIMUM_REQUIREMENT = 3 SERVER_LIST = [ "tikv-server-01", "tikv-server-02", "tikv-server-03" ] [production.tiflash_cluster] INSTANCE_TYPE = "i4g.16xlarge" RESOURCE.CPU = "48 core+" RESOURCE.MEMORY = "128 GB+" RESOURCE.STORAGE = "1 or more SSDs" RESOURCE.NETWORK = "10 Gigabit network card (2 preferred)" RESOURCE.MINIMUM_REQUIREMENT = 2 SERVER_LIST = [ "tiflash-server-01", "tiflash-server-02" ] [production.monitor] INSTANCE_TYPE = "t4g.2xlarge" RESOURCE.CPU = "8 core+" RESOURCE.MEMORY = "16 GB+" RESOURCE.STORAGE = "SAS" RESOURCE.NETWORK = "Gigabit network card" RESOURCE.MINIMUM_REQUIREMENT = 1 SERVER_LIST = [ "monitor-server-01" ]
libs
toml-config-displayで使用するPythonのモジュールです
-
toml_toolkit.py
- TOMLを読み込むための共通モジュール
- TOMLを読み込むための共通モジュール
-
tcd_config.py
- 「toml_toolkit.py」を使用してTOMLファイルの読み込み及び、設定ファイル用に加工するためのモジュール
- 「toml_toolkit.py」を使用してTOMLファイルの読み込み及び、設定ファイル用に加工するためのモジュール
-
display_toolkit.py
- 表示用の共通モジュール
toml_toolkit_py
-
toml_toolkit.py
#!/usr/bin/env python3 # -*- coding: utf-8 -*- """ GLOBAL変数初期化 """ # ライブラリインポート import toml # TOML """ toml_toolkit.py -------------------------------------------------------- TOML共通モジュール """ def f_read_toml(in_toml_path, in_key): with open(in_toml_path, "r") as file: ret_value = toml.load(file) if in_key != None: ret_value = ret_value[in_key] return ret_value def f_get_toml_table(in_toml_path, in_key): toml_object = f_read_toml(in_toml_path, in_key) ret_value = [] for key in toml_object.keys(): if isinstance(toml_object[key], dict): ret_value.append(key) return ret_value def f_search_toml(in_toml_object, in_toml_table, in_toml_key): ret_value = in_toml_object[in_toml_table][in_toml_key] return ret_value
tcd_config_py
-
tcd_config.py
#!/usr/bin/env python3 # -*- coding: utf-8 -*- """ GLOBAL変数初期化 """ # ライブラリインポート import os # OS import libs.toml_toolkit as toml_toolkit # コンスタント TCD_BASE_PATH = os.path.abspath("..") TCD_CONFIG_PATH = os.path.join(TCD_BASE_PATH, "config") COMMON_TOML_PATH = os.path.join(TCD_CONFIG_PATH, "common.toml") TCD_GENERAL_TOML_PATH = os.path.join(TCD_CONFIG_PATH, "tcd_general.toml") TCD_TIDB_TOML_PATH = os.path.join(TCD_CONFIG_PATH, "tcd_tidb.toml") """ tcd_config.py -------------------------------------------------------- tomlパラメータ設定モジュール """ class CommonToml: def __init__(self): self.environment_list = None def read_toml(self): common_toml = toml_toolkit.f_read_toml(COMMON_TOML_PATH, None) # [environment_info] self.environment_list = toml_toolkit.f_search_toml(common_toml, "environment_info", "ENVIRONMENT_LIST") class GeneralToml: def __init__(self): self.tcd_root_dir = None self.tcd_config_dir = None self.tcd_script_dir = None self.tcd_libs_dir = None self.tcd_general_toml = None self.tcd_tidb_toml = None self.display_general_toml_py = None self.display_tidb_toml_py = None self.tcd_config_py = None self.toml_toolkit_py = None self.display_toolkit_py = None def read_toml(self): self.tcd_base_path = TCD_BASE_PATH tcd_general_toml = toml_toolkit.f_read_toml(TCD_GENERAL_TOML_PATH, None) # [setup_info] self.tcd_root_dir = toml_toolkit.f_search_toml(tcd_general_toml, "setup_info", "TCD_ROOT_DIR") self.tcd_config_dir = toml_toolkit.f_search_toml(tcd_general_toml, "setup_info", "TCD_CONFIG_DIR") self.tcd_script_dir = toml_toolkit.f_search_toml(tcd_general_toml, "setup_info", "TCD_SCRIPT_DIR") self.tcd_libs_dir = toml_toolkit.f_search_toml(tcd_general_toml, "setup_info", "TCD_LIBS_DIR") # [config_info] self.tcd_general_toml = toml_toolkit.f_search_toml(tcd_general_toml, "config_info", "TCD_GENERAL_TOML") self.tcd_tidb_toml = toml_toolkit.f_search_toml(tcd_general_toml, "config_info", "TCD_TIDB_TOML") # [script_info] self.display_general_toml_py = toml_toolkit.f_search_toml(tcd_general_toml, "script_info", "DISPLAY_GENERAL_TOML_PY") self.display_tidb_toml_py = toml_toolkit.f_search_toml(tcd_general_toml, "script_info", "DISPLAY_TIDB_TOML_PY") # [libs_info] self.tcd_config_py = toml_toolkit.f_search_toml(tcd_general_toml, "libs_info", "TCD_CONFIG_PY") self.toml_toolkit_py = toml_toolkit.f_search_toml(tcd_general_toml, "libs_info", "TOML_TOOLKIT_PY") self.display_toolkit_py = toml_toolkit.f_search_toml(tcd_general_toml, "libs_info", "DISPLAY_TOOLKIT_PY") ############################## # カスタム設定 ############################## self.args_path_list = [] # configパス設定 self.config_path = os.path.join(self.tcd_base_path, self.tcd_config_dir) self.tcd_general_toml_fullpath = os.path.join(self.config_path, self.tcd_general_toml) self.tcd_tidb_toml_fullpath = os.path.join(self.config_path, self.tcd_tidb_toml) self.args_path_list.append([self.tcd_config_dir, self.tcd_general_toml_fullpath, self.tcd_tidb_toml_fullpath]) # scriptパス設定 self.script_path = os.path.join(self.tcd_base_path, self.tcd_script_dir) self.display_general_toml_py_fullpath = os.path.join(self.script_path, self.display_general_toml_py) self.display_tidb_toml_py_fullpath = os.path.join(self.script_path, self.display_tidb_toml_py) self.args_path_list.append([self.tcd_script_dir, self.display_general_toml_py_fullpath, self.display_tidb_toml_py_fullpath]) # libパス設定 libs_path = os.path.join(self.script_path, self.tcd_libs_dir) self.tcd_config_py_fullpath = os.path.join(libs_path, self.tcd_config_py) self.toml_toolkit_py_fullpath = os.path.join(libs_path, self.toml_toolkit_py) self.display_toolkit_py_fullpath = os.path.join(libs_path, self.display_toolkit_py) self.args_path_list.append([self.tcd_libs_dir, self.tcd_config_py_fullpath, self.toml_toolkit_py_fullpath, self.display_toolkit_py_fullpath]) class TidbToml: def __init__(self, in_environment_type, in_cluster_type): self.environment_type = in_environment_type self.cluster_type = in_cluster_type self.cpu = None self.memory = None self.storage = None self.network = None self.minimum_requirement = None def read_toml(self): tcd_tidb_toml = toml_toolkit.f_read_toml(TCD_TIDB_TOML_PATH, self.environment_type) self.instance_type = toml_toolkit.f_search_toml(tcd_tidb_toml, self.cluster_type, "INSTANCE_TYPE") result = toml_toolkit.f_search_toml(tcd_tidb_toml, self.cluster_type, "RESOURCE") self.cpu = result["CPU"] self.memory = result["MEMORY"] self.storage = result["STORAGE"] self.network = result["NETWORK"] self.minimum_requirement = result["MINIMUM_REQUIREMENT"] def get_toml_table(self): result = toml_toolkit.f_get_toml_table(TCD_TIDB_TOML_PATH, self.environment_type) return result
display_toolkit_py
-
display_toolkit.py
#!/usr/bin/env python3 # -*- coding: utf-8 -*- """ GLOBAL変数初期化 """ # ライブラリインポート import textwrap # ヒアドキュメント """ display_toolkit.py -------------------------------------------------------- 表示用共通モジュール """ def f_display_argument_error(in_item_name, in_argument, in_argument_list): environment_errorr_message = textwrap.dedent(''' [{item_name}エラー] +---------------------------------------------------------------------------------+ {item_name}に「{argument}」が設定されています。 パラメータ「{item_name}」は {argument_list} を設定してください +---------------------------------------------------------------------------------+ ''').format(item_name=in_item_name, argument=in_argument, argument_list=in_argument_list).strip() print("{} {}".format(environment_errorr_message, "\n")) def f_display_division(in_action_type, in_division_type, in_finish): if in_division_type == "start": start_message = textwrap.dedent(''' [{action_type}] +---------------------------------------------------------------------------------+ ''').format(action_type=in_action_type).strip() print(start_message) elif in_division_type == "finish": finish_message = textwrap.dedent(''' {finish} +---------------------------------------------------------------------------------+ ''').format(finish=in_finish).strip() print("{} {}".format(finish_message, "\n"))
tomlcd
TOMLを表示するためのPythonのメインモジュールです
-
display_general_toml.py
- 「tcd_general.toml」を表示するサンプルスクリプト
- 「tcd_general.toml」を表示するサンプルスクリプト
-
display_tidb_toml.py
- 「tcd_tidb.toml」を表示するサンプルスクリプト
display_general_toml_py
-
display_general_toml.py
#!/usr/bin/env python3 # -*- coding: utf-8 -*- """ GLOBAL変数初期化 """ # ライブラリインポート import inspect # ファンクション名取得 import libs.tcd_config as tcd_config import libs.display_toolkit as display_toolkit """ display_general_toml.py -------------------------------------------------------- 「tdc_general.toml」表示モジュール """ # config read tcd_general_toml = tcd_config.GeneralToml() tcd_general_toml.read_toml() def f_display_general_toml_01(): function_name = inspect.currentframe().f_code.co_name """ f_display_division """ display_toolkit.f_display_division(function_name, "start", "") print("[{}]".format(tcd_general_toml.tcd_config_dir)) print(tcd_general_toml.tcd_general_toml_fullpath) print(tcd_general_toml.tcd_tidb_toml_fullpath) print("[{}]".format(tcd_general_toml.tcd_script_dir)) print(tcd_general_toml.display_general_toml_py_fullpath) print(tcd_general_toml.display_tidb_toml_py_fullpath) print("[{}]".format(tcd_general_toml.tcd_libs_dir)) print(tcd_general_toml.tcd_config_py_fullpath) print(tcd_general_toml.toml_toolkit_py_fullpath) print(tcd_general_toml.display_toolkit_py_fullpath) """ f_display_division """ display_toolkit.f_display_division(function_name, "finish", "") def f_display_general_toml_02(): function_name = inspect.currentframe().f_code.co_name """ f_display_division """ display_toolkit.f_display_division(function_name, "start", "") print("{}".format(inspect.currentframe().f_code.co_name)) for args_path_list in tcd_general_toml.args_path_list: print("[{}]".format(args_path_list[0])) for path_info in args_path_list[1:]: print(path_info) """ f_display_division """ display_toolkit.f_display_division(function_name, "finish", "") def f_main(): """ f_display_general_toml_01 """ f_display_general_toml_01() """ f_display_general_toml_02 """ f_display_general_toml_02() """ main """ if __name__ == '__main__': f_main()
display_tidb_toml_py
-
display_tidb_toml.py
#!/usr/bin/env python3 # -*- coding: utf-8 -*- """ GLOBAL変数初期化 """ # ライブラリインポート import sys # SYS import textwrap # ヒアドキュメント import libs.tcd_config as tcd_config import libs.display_toolkit as display_toolkit """ display_tidb_toml.py -------------------------------------------------------- 「tdc_tidb.toml」表示モジュール """ # config read common_toml = tcd_config.CommonToml() common_toml.read_toml() tcd_general_toml = tcd_config.GeneralToml() tcd_general_toml.read_toml() def f_check_argument(in_environment_list): # パラメータ設定 in_args = sys.argv try: if len(in_args) == 3: return True, str(in_args[1]), str(in_args[2]) else: raise argument_error except Exception as argument_error: error_message = textwrap.dedent(''' パラメータの設定は下記の通り設定してください +---------------------------------------------------------------------------------+ 第1パラメータに「環境のタイプ」 第2パラメータに「クラスタータイプ」を設定してください 環境のタイプ : {nvironment_list} クラスタータイプ : 「ALL」を入力すると「環境のタイプ」に関連する全てのクラスターが表示されます +---------------------------------------------------------------------------------+ ''').format(nvironment_list=in_environment_list).strip() print("{} {}".format(error_message, "\n")) return False, None def f_display_cluster_info(in_environment_type, in_cluster_type): tcd_tidb_toml = tcd_config.TidbToml(in_environment_type, in_cluster_type) tcd_tidb_toml.read_toml() environment_message = textwrap.dedent(''' [{cluster_type}] +---------------------------------------------------------------------------------+ Instance Type: {instance_type} CPU : {cpu} Memory : {memory} Storage : {storage} Network : {network} Number of Instances(Minimum Requirement) : {minimum_requirement} +---------------------------------------------------------------------------------+ ''').format(cluster_type=in_cluster_type, instance_type=tcd_tidb_toml.instance_type, cpu=tcd_tidb_toml.cpu, memory=tcd_tidb_toml.memory, storage=tcd_tidb_toml.storage, network=tcd_tidb_toml.network, minimum_requirement=tcd_tidb_toml.minimum_requirement).strip() print("{} {}".format(environment_message, "\n")) def f_main(): """ f_check_param """ result = f_check_argument(common_toml.environment_list) if result[0] == True: environment_type, cluster_type = result[1], result[2] else: sys.exit() if environment_type in common_toml.environment_list: tcd_tidb_toml = tcd_config.TidbToml(environment_type, None) component_list = tcd_tidb_toml.get_toml_table() if cluster_type in component_list or cluster_type.upper() == "ALL": if cluster_type.upper() == "ALL": for cluster_name in component_list: """ f_display_cluster_info """ f_display_cluster_info(environment_type, cluster_name) else: """ f_display_cluster_info """ f_display_cluster_info(environment_type, cluster_type) else: """ f_display_argument_error """ display_toolkit.f_display_argument_error("cluster_type", cluster_type, component_list) else: """ f_display_argument_error """ display_toolkit.f_display_argument_error("environment_type", environment_type, common_toml.environment_list) """ main """ if __name__ == '__main__': f_main()
セットアップ手順
上記サンプルスクリプトをセットアップして実行するまでの手順を記載していきます
環境について
スクリプトを確認した環境は下記になります。
尚、今回使用した環境はMacになりますが、環境に依存しない作りにしているため異なる環境(例えばWindows)でもスクリプトは動くかと思います
- MacBook Pro(Apple M2)
- macOS Ventura(13.5.2)
- Pythonのバージョン(3.11.4)
仮想環境準備
必要に応じて下記をインストールしてください
今回の記事で「pyenv」や「virtualenv」のインストール及び、設定に関して記載するかどうか?迷ったのですが、今回はそこまでは記載しないことにします。
- pyenv
- Pythonのバージョンを固定する場合
- virtualenv
- 環境汚染を防止する場合
- Pythonモジュールのバージョンを固定する場合
事前準備
ソースコード公開用のGitHubを用意してcloneする方が導入が楽なのですが、お手数ですが各スクリプトをコピーして試していただければと思います。
スクリプトの配置やPythonモジュール(TOML)をセットアップします
- スクリプトの配置について
- セットアップスクリプトも準備していますので、手順に沿って実施ください。
- セットアップスクリプトも準備していますので、手順に沿って実施ください。
- Pythonモジュールのインストールについて
- requirements.txtには今回使用したバージョンが記載されていますが、必要に応じて最新のバージョンをインストールことも可能です。
python3 -m pip install toml
- requirements.txtには今回使用したバージョンが記載されていますが、必要に応じて最新のバージョンをインストールことも可能です。
- スクリプトを配置
下記のステップを実施してください
a. 環境構築するディレクトリに移動して「tcd_setup.py」を作成
b. 「tcd_setup.py」モジュールを実行c. 「ソースコード構成」と同じ構成であることを確認python3 -m tcd_setup
d. 「ソースコード内容」のソースコードを作成ファイルに登録
- Pythonモジュールをインストール
a. Pythonモジュールのインストール状況を確認b.「toml-config-display」ディレクトリに移動pip3 freeze | grep toml
c. Pythonモジュールをインストールpip3 install -r requirements.txt
スクリプト実行
各スクリプトを実行後にTOMLの情報を取得して表示します
-
display_general_toml.py
- 「tcd_general.toml」のデータを表示します
- テーブルによる階層がないため値の取得方法を変化させました
出力結果は同じですが実行しているファンクションを分けています- f_display_general_toml_01
- TOMLの値を個別で表示
- f_display_general_toml_02
- TOMLの値を配列に格納してLOOPで表示
- TOMLの値を配列に格納してLOOPで表示
- f_display_general_toml_01
-
display_tidb_toml.py
- 「tcd_tidb.toml」のデータを表示します
- テーブル毎に階層を分けているため入力パラメータによって様々な条件でTOMLの内容を表示しています
- 例)development、production、tidb_cluster、etc.
- スクリプトの入力パラメータ
- 第1パラメータ:development、production
- 第2パラメータ:tidb_cluster、ALL、etc.
- スクリプトの入力パラメータがあるため入力チェックを行います
- スクリプトの入力チェックにはTOMLのテーブルのリストを評価しています。そのため設定パラメータによって評価の対象も動的に変化する仕組みになっています
- 例)development、productionの階層に「staging、test、etc.」を追加するとチェック対象が自動で増えます
- スクリプトのプロジェクトパス(「tomlcd」)へ移動
- スクリプト実行
- 「display_general_toml.py」を実行
- コマンド
python3 -m display_general_toml
- 結果
[f_display_general_toml_01] +---------------------------------------------------------------------------------+ [config] /opt/alt/toml-config-display/config/tcd_general.toml /opt/alt/toml-config-display/config/tcd_tidb.toml [tomlcd] /opt/alt/toml-config-display/tomlcd/display_general_toml.py /opt/alt/toml-config-display/tomlcd/display_tidb_toml.py [libs] /opt/alt/toml-config-display/tomlcd/libs/tcd_config.py /opt/alt/toml-config-display/tomlcd/libs/toml_toolkit.py /opt/alt/toml-config-display/tomlcd/libs/display_toolkit.py +---------------------------------------------------------------------------------+ [f_display_general_toml_02] +---------------------------------------------------------------------------------+ f_display_general_toml_02 [config] /opt/alt/toml-config-display/config/tcd_general.toml /opt/alt/toml-config-display/config/tcd_tidb.toml [tomlcd] /opt/alt/toml-config-display/tomlcd/display_general_toml.py /opt/alt/toml-config-display/tomlcd/display_tidb_toml.py [libs] /opt/alt/toml-config-display/tomlcd/libs/tcd_config.py /opt/alt/toml-config-display/tomlcd/libs/toml_toolkit.py /opt/alt/toml-config-display/tomlcd/libs/display_toolkit.py +---------------------------------------------------------------------------------+
- コマンド
- 「display_tidb_toml.py」を実行
こちらはいくつかのパターンがありますので例を表示します- 例)「tcd_tidb.toml」のテーブル「development」を全て表示する場合
- コマンド
python3 -m display_tidb_toml development ALL
- 結果
[tidb_cluster] +---------------------------------------------------------------------------------+ Instance Type: t4g.2xlarge CPU : 8 core+ Memory : 16 GB+ Storage : No special requirements Network : Gigabit network card Number of Instances(Minimum Requirement) : 1 +---------------------------------------------------------------------------------+ [pd_cluster] +---------------------------------------------------------------------------------+ Instance Type: t4g.xlarge CPU : 4 core+ Memory : 8 GB+ Storage : SAS, 200 GB+ Network : Gigabit network card Number of Instances(Minimum Requirement) : 1 +---------------------------------------------------------------------------------+ [tikv_cluster] +---------------------------------------------------------------------------------+ Instance Type: i4g.2xlarge CPU : 8 core+ Memory : 32 GB+ Storage : SAS, 200 GB+ Network : Gigabit network card Number of Instances(Minimum Requirement) : 3 +---------------------------------------------------------------------------------+
- コマンド
- 例)「tcd_tidb.toml」のテーブル「development.tidb_cluster」を表示する場合
- コマンド
python3 -m display_tidb_toml development tidb_cluster
- 結果
[tidb_cluster] +---------------------------------------------------------------------------------+ Instance Type: t4g.2xlarge CPU : 8 core+ Memory : 16 GB+ Storage : No special requirements Network : Gigabit network card Number of Instances(Minimum Requirement) : 1 +---------------------------------------------------------------------------------+
- コマンド
- 例)「tcd_tidb.toml」のテーブル「production.tikv_cluster」を表示する場合
- コマンド
python3 -m display_tidb_toml production tikv_cluster
- 結果
[tikv_cluster] +---------------------------------------------------------------------------------+ Instance Type: i4g.4xlarge CPU : 16 core+ Memory : 64 GB+ Storage : SSD Network : 10 Gigabit network card (2 preferred) Number of Instances(Minimum Requirement) : 3 +---------------------------------------------------------------------------------+
- コマンド
- 例)「tcd_tidb.toml」のテーブル「development」を全て表示する場合
仕組みについての解説
「tcd_general.toml」のデータを
display_general_toml.pyでどのように取得しているのか?を最後に解説しておきます
尚、取得対象はテーブル「setup_info」のキー「TCD_CONFIG_DIR」で値「"config"」を取得する例になります
データの流れ
- 上記イメージは「display_general_toml.py」を実行してから結果が表示されるまでの流れになります
- スクリプトを実行
- 番号の順番通りに遷移
- 結果を表示
- 色によって識別できるようにしています
- 同色であれば参照先や関係は同じになります
解説
- 上記スクリプト実行の流れを解説します
- 「display_general_toml.py」を実行
- 「tcd_config.py」のClass「GeneralToml」をインスタンス化
- インスタンス化した「GeneralToml」の「read_toml」を実行
- 「toml_toolkit.py」の「f_read_toml」を使用して
「tcd_general.toml」のデータを全件ロード - TABLE(setup_info)、KEY(TCD_CONFIG_DIR)
からVALUE("config")を取得
- 「toml_toolkit.py」の「f_read_toml」を使用して
- 「tcd_general_toml.tcd_root_dir」をprintすると
値「"config"」が表示されます
- 「display_general_toml.py」を実行
まとめ
PythonでTOMLを使うための仕組みについて
どの様にTOMLのデータを取得しているのか?
サンプルスクリプトを使用して解説を行いました!!
今回公開しましたスクリプトは自由にお使いくださいませーー
スクリプトをそのまま使うでもよし!
自分達でもっと使いやすく修正して使うでもよし!!
今回載せたスクリプトが皆さんのお役に立てたら幸いです!!
また、Pythonで使用しないにせよ、
TOMLはシンプルで使いやすいのでお勧めですーー!!
様々な言語に対応していますので、
是非是非お使いくださいーー
(TOMLの回し者ではないですよw)