DNA Center でよく使う CLI コマンド magctl, maglev はどちらも Python スクリプトとして実装されています。この内、magctl コマンドは主に kubectl, docker など DNA Center で使用されている OSS のコマンドの wrapper として機能します。
[Sun Apr 26 04:39:22 UTC] maglev@10.70.70.231 (maglev-master-1) ~
$ which magctl
/usr/local/bin/magctl
[Sun Apr 26 04:48:54 UTC] maglev@192.0.2.1 (maglev-master-1) ~
$ cat /usr/local/bin/magctl
#!/opt/maglev/bin/python
# -*- coding: utf-8 -*-
import re
import sys
from magctl.main import cli # モジュール読み込み
if __name__ == '__main__':
sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0])
sys.exit(cli())
モジュールの定義を参照すれば実行する処理をご確認いただけますので、内容を把握したり、Cisco 独自の様式ではなく標準的な OSS の CLI で操作したい方の参考にしていただけます。
例えば magctl service attach コマンドであれば以下のように対象となるコンテナを検索し、 --docker (-D) オプションに応じて kubectl exec -it または docker exec -it を実行することが分かります。(古いバージョンでは kubectl attach -it を実行します)
[Sun Apr 26 04:51:37 UTC] maglev@192.0.0.1 (maglev-master-1) commands
$ magctl service attach --help
Usage: magctl service attach [OPTIONS] SERVICE
Connects to the bash shell of a currently running instance of SERVICE
Options:
-c, --container TEXT name of container to which to connect
-a, --appstack TEXT AppStack on which to perform the operation
-i, --image TEXT Docker image for service
-D, --docker Use docker to attach
--help Show this message and exit.
[Sun Apr 26 04:51:43 UTC] maglev@192.0.2.1 (maglev-master-1) commands
$ pwd
/opt/maglev/lib/python2.7/site-packages/magctl/commands
[Sun Apr 26 04:51:47 UTC] maglev@192.0.2.1 (maglev-master-1) commands
$ ls *.py
__init__.py api.py appstack.py completion.py disk.py etcd.py glusterfs.py iam.py job.py logs.py maglev.py node.py password_manager.py service.py ssh.py sts.py system.py tenant.py token.py user.py workflow.py
[Sun Apr 26 04:52:03 UTC] maglev@192.0.0.1 (maglev-master-1) commands
$ cat service.py
from magctl.command import DockerCommandBuilder, KubectlCommandBuilder
@click.command()
@click.argument("service")
@click.option("--container", "-c", help="name of container to which to connect")
@click.option("--appstack", "-a", help="AppStack on which to perform the operation")
@click.option("--image", "-i", help="Docker image for service")
@click.option("--docker", "-D", is_flag=True, help="Use docker to attach")
def attach(service, container, appstack, image, docker):
"""Connects to the bash shell of a currently running instance of SERVICE"""
log_debug_message(0, "Search matching pod using service: [%s]", service)
match = _search_for_pod(service, namespace=appstack) # 該当 Pod の検索
namespace = appstack if appstack else match.group("namespace")
# determine dimensions of current terminal session
rows, columns = os.popen("stty size").read().split()
if not docker: # --docker (-D) オプションの有無
cmd = KubectlCommandBuilder("exec", match.group("name"), "--namespace", namespace) # kubectl コマンドの組み立て
if container:
cmd.append("-c", container)
print("")
log_status(0, "Attaching to '%s/%s'", namespace, match.group("name"))
return cmd.append("-it", "env", "COLUMNS=%s" % columns, "LINES=%s" % rows, "TERM=xterm", "/bin/bash").run() # /bin/bash 実行
else:
if not container:
container = service
log_debug_message(0, "Search docker image using container-name: [%s]", container)
if not image:
image = KubectlCommandBuilder("get", "pods", match.group("name"), "--namespace", namespace,
"-o=jsonpath={.spec.containers[?(@.name==\"%s\")].image}"
% container).run(capture_output=True)
log_debug_message(0, "Search container-id using docker image: [%s]", image)
id_list = _search_for_container_id(service, image=image, namespace=appstack)
if not id_list:
exit_with_error(0, "No container matches found, may be the docker container is running on another node?")
if len(id_list) > 1:
exit_with_error(0, "Multiple matches found. Specify a container ID\n\t%s\n",
"\n\t".join(id_list))
container_id = id_list[0]
print("")
log_status(0, "Attaching to '%s/%s'", namespace, match.group("name"))
return DockerCommandBuilder("exec", "-it", "--env", "COLUMNS=%s" % columns, "--env", "LINES=%s" % rows,
"--env", "TERM=xterm", container_id, "/bin/bash").run_interactive() # docker exec -it 実行