×
Community Blog Program Shortcut Send Command In Jinja2 Template To ECS Without Internet Connection

Program Shortcut Send Command In Jinja2 Template To ECS Without Internet Connection

Program Shortcut Send Command In Jinja2 Template To ECS Without Internet Connection

Install ECS SDK

pip install --upgrade pip pyyaml jinja2 alibabacloud_ecs20140526
  • alibabacloud_ecs20140526 : call API control ECS machine
  • jinja2 : render script from template and variables
  • pyyaml : read yaml file

Create VSCode Shortcut

  • crtl+K+S append this content to file keybindings.json
[
  {
    "key": "ctrl+shift+3",
    "command": "workbench.action.terminal.sendSequence",
    "args": {
      "text": "python3 /code/.vscode/execute.py ${file} 3\u000D"
    }
  }
]
  • When ctrl+shift+3, module execute.py will send command in current file selected to the target ECS

Handle Shortcut Execute

Append this content to file /code/.vscode/execute.py to handle shortcut execute

import os, sys, yaml, time, base64, uuid
from alibabacloud_ecs20140526.models import *

class AlicloudECS:
  def __init__(self, access, secret, region):
    from alibabacloud_tea_openapi.models import Config
    from alibabacloud_ecs20140526.client import Client
    self.client = Client(Config(
      access_key_id = access,
      access_key_secret = secret,
      endpoint = f'ecs.{region}.aliyuncs.com',
    ))
    self.region_id = region

  def describe_invocations(self, invoke_id):
    return self.client.describe_invocations(DescribeInvocationsRequest(
      invoke_id = invoke_id,
      region_id = self.region_id,
    )).body.invocations.invocation

  def create_command(self, command_content):
    res = self.client.create_command(CreateCommandRequest(
      name = str(uuid.uuid4()),
      type = 'RunShellScript',
      command_content = base64.b64encode(command_content.encode('UTF-8')),
      working_dir = '/root',
      region_id = self.region_id,
    ))
    return res.body.command_id

  def describe_invocation_results(self, invoke_id, command_id):
    res = self.client.describe_invocation_results(DescribeInvocationResultsRequest(
      invoke_id = invoke_id,
      command_id = command_id,
      region_id = self.region_id,
    ))
    res = res.body.invocation.invocation_results.invocation_result[0].output
    return base64.b64decode(res).decode('UTF-8')

  def delete_command(self, command_id):
    self.client.delete_command(DeleteCommandRequest(
      command_id = command_id,
      region_id = self.region_id,
    ))

  def invoke_command(self, instance_id, command_content):
    print('[ECS Invoke Command]')
    command_id = self.create_command(command_content)

    res = self.client.invoke_command(InvokeCommandRequest(
      command_id = command_id,
      instance_id = [instance_id],
      region_id = self.region_id,
    ))
    invoke_id = res.body.invoke_id

    check = lambda: self.describe_invocations(invoke_id)[0]
    res = check()
    while res.invoke_status != 'Finished':
      if res.invoke_status == 'Stopped':
        raise RuntimeError()
      print('[ECS Invoke Command] Working...')
      time.sleep(10)
      res = check()
    print('[ECS Invoke Command] Done')

    res = self.describe_invocation_results(invoke_id, command_id)
    self.delete_command(command_id)
    return res


class Exe:
  def __init__(self, absolute_path, mode):
    self.path = absolute_path
    self.mode = str(mode).strip()
    tmp = self.path.split('/')
    self.name = tmp[-1]
    self.ext =  self.name.split('.')[-1]
    self.folder = '/'.join(tmp[:-1])
    if mode == '3':
      self.invoke()

  def invoke(self):
    import jinja2

    with open(self.path, 'r') as f:
      content = f.read()
    content = content.split('\n')

    target = content[0][1:].strip()
    file_input = content[1][1:].strip()
    file_output = content[2][1:].strip()
    content = '\n'.join(content[3:]).strip()
    file_input = yaml.safe_load(open(file_input, 'r'))
    content = jinja2.Template(content).render(**file_input)

    login = yaml.safe_load(open('secret/credential.yml', 'r'))
    ECS = AlicloudECS (login['access'], login['secret'], login['region'])
    res_output = ECS.invoke_command(target, content)
    with open(file_output, 'w') as f:
      f.write(res_output)

absolute_path, mode, *_ = sys.argv[1:]
Exe(absolute_path, mode)

Access Key

Put RAM access key of the ECS to file /code/secret/credential.yml

access: LTA*****
secret: ********
region: ap-southeast-1

Example

  • Get InstanceID of the ECS (i-t4n7od2o6tt3mnkmnogk in my case)
    MreckBcKQENYLAkdfi4OKoqXqUW1rJ9J6lXkjoZT
  • Create file /code/info.yml contain all parameters
hello: Hello World!
files: [file1, file2, file3]
  • Create file /code/script.sh is template in Jinja2 format and script you want send to the ECS

    • 1st row comment : InstanceID of the target ECS
    • 2nd row comment : Path to file contain parameter
    • 3rd row comment : Path to file contain the result of command
# i-t4n7od2o6tt3mnkmnogk
# info.yml
# output.log

apt update

echo {{hello}} > /tmp/hello

{% for item in files -%}
  touch /tmp/{{ item }}
{% endfor -%}
  • Select file /code/script.sh in VSCode and excute shortcut ctrl+shift+3

w9M39BLsuI0ygeBlkz0HKa7X66Difi7lvAlRxnIk

  • Check the result on file /code/output.log
    T5BbTgpym8Qdl7J549U8TJifWXUZnlNuCfCggtoY
  • Check the result on Web console
    epPDP48NcgYlh2YlU6eO4WMFIKfSKsLPSp7CWTE1

FmSBLvbJxRLN6O7mjbvyp7HfLFcITuNbs5Y1P4eL

0 2 0
Share on

quangnn

8 posts | 0 followers

You may also like

Comments