much better cli

This commit is contained in:
ahmadbilalkhalid 2019-07-17 19:58:39 +05:00
parent c4cf097b99
commit d045d70609
11 changed files with 210 additions and 121 deletions

1
.gitignore vendored
View File

@ -2,3 +2,4 @@ venv/
.idea/ .idea/
.vscode/ .vscode/
.env .env
__pycache__/

View File

@ -9,6 +9,7 @@ verify_ssl = true
requests = "*" requests = "*"
python-decouple = "*" python-decouple = "*"
pyotp = "*" pyotp = "*"
click = "*"
[requires] [requires]
python_version = "3.7" python_version = "3.7"

10
Pipfile.lock generated
View File

@ -1,7 +1,7 @@
{ {
"_meta": { "_meta": {
"hash": { "hash": {
"sha256": "e9d4e4efe74bd8386357563e682181c69cbbc66d40fc02931fd0f730ae6053e4" "sha256": "1f6e0448a1e04906885393b4ff57423363593680a7b6f73a5ed1f514496bb1f3"
}, },
"pipfile-spec": 6, "pipfile-spec": 6,
"requires": { "requires": {
@ -30,6 +30,14 @@
], ],
"version": "==3.0.4" "version": "==3.0.4"
}, },
"click": {
"hashes": [
"sha256:2335065e6395b9e67ca716de5f7526736bfa6ceead690adf616d925bdc622b13",
"sha256:5b94b49521f6456670fdb30cd82a4eca9412788a93fa6dd6df72c94d5a8ff2d7"
],
"index": "pypi",
"version": "==7.0"
},
"idna": { "idna": {
"hashes": [ "hashes": [
"sha256:c357b3f628cf53ae2c4c05627ecc484553142ca23264e593d327bcde5e9c3407", "sha256:c357b3f628cf53ae2c4c05627ecc484553142ca23264e593d327bcde5e9c3407",

0
commands/__init__ Normal file
View File

30
commands/host.py Normal file
View File

@ -0,0 +1,30 @@
import click
import json
import requests
from decouple import config
from helper import OTPCredentials
@click.group()
def host():
pass
@host.command("add")
@click.option("--name", required=True)
@click.option("--realm", required=True)
@click.option("--seed", required=True)
@click.option("--specs", required=True)
@click.option("--hostname", required=True)
def add_host(name, realm, seed, specs, hostname):
with open(specs, "r") as specs_f:
specs = json.loads(specs_f.read())
data = {
**OTPCredentials(name, realm, seed).get_json(),
"specs": specs,
"hostname": hostname,
}
r = requests.post(f"{config('UCLOUD_API_SERVER')}/host/create", json=data)
print(json.loads(r.content))

30
commands/image.py Normal file
View File

@ -0,0 +1,30 @@
import click
import json
import requests
from decouple import config
from helper import OTPCredentials
@click.group()
def image():
pass
@image.command("list")
@click.option("--public", is_flag=True)
@click.option("--private", is_flag=True)
def list(public, private):
if public:
r = requests.get(f"{config('UCLOUD_API_SERVER')}/image/list-public")
print(json.loads(r.content))
@image.command("create-from-file")
@click.option("--name", required=True)
@click.option("--uuid", required=True)
@click.option("--image_store_name", required=True)
def create_from_file(name, uuid, image_store_name):
data = {"name": name, "uuid": uuid, "image_store": image_store_name}
r = requests.post(f"{config('UCLOUD_API_SERVER')}/image/create", data)
print(r.content.decode("utf-8"))

31
commands/user.py Normal file
View File

@ -0,0 +1,31 @@
import click
import json
import requests
from decouple import config
from helper import OTPCredentials
@click.group()
def user():
pass
@user.command("list-files")
@click.option("--name", required=True)
@click.option("--realm", required=True)
@click.option("--seed", required=True)
def list_files(name, realm, seed):
data = OTPCredentials(name, realm, seed).get_json()
r = requests.get(f"{config('UCLOUD_API_SERVER')}/user/files", json=data)
print(json.loads(r.content))
@user.command("list-vms")
@click.option("--name", required=True)
@click.option("--realm", required=True)
@click.option("--seed", required=True)
def list_vms(name, realm, seed):
data = OTPCredentials(name, realm, seed).get_json()
r = requests.get(f"{config('UCLOUD_API_SERVER')}/user/vms", json=data)
print(json.loads(r.content))

75
commands/vm.py Normal file
View File

@ -0,0 +1,75 @@
import click
import json
import requests
from decouple import config
from helper import OTPCredentials
def vm_action(action, otp, vmid):
data = {**otp.get_json(), "vmid": vmid}
r = requests.post(f"{config('UCLOUD_API_SERVER')}/vm/{action}", json=data)
return r
@click.group()
def vm():
pass
@vm.command("create")
@click.option("--name", required=True)
@click.option("--realm", required=True)
@click.option("--seed", required=True)
@click.option("--specs", required=True)
@click.option("--image_uuid", required=True)
def create(name, realm, seed, specs, image_uuid):
with open(specs, "r") as specs_f:
specs = json.loads(specs_f.read())
data = {
**OTPCredentials(name, realm, seed).get_json(),
"specs": specs,
"image_uuid": image_uuid,
}
r = requests.post(f"{config('UCLOUD_API_SERVER')}/vm/create", json=data)
print(json.loads(r.content))
@vm.command("start")
@click.option("--name", required=True)
@click.option("--realm", required=True)
@click.option("--seed", required=True)
@click.option("--vmid", required=True)
def start(name, realm, seed, vmid):
r = vm_action("start", OTPCredentials(name, realm, seed), vmid)
print(json.loads(r.content))
@vm.command("suspend")
@click.option("--name", required=True)
@click.option("--realm", required=True)
@click.option("--seed", required=True)
@click.option("--vmid", required=True)
def suspend(name, realm, seed, vmid):
r = vm_action("suspend", OTPCredentials(name, realm, seed), vmid)
print(json.loads(r.content))
@vm.command("resume")
@click.option("--name", required=True)
@click.option("--realm", required=True)
@click.option("--seed", required=True)
@click.option("--vmid", required=True)
def resume(name, realm, seed, vmid):
r = vm_action("resume", OTPCredentials(name, realm, seed), vmid)
print(json.loads(r.content))
@vm.command("shutdown")
@click.option("--name", required=True)
@click.option("--realm", required=True)
@click.option("--seed", required=True)
@click.option("--vmid", required=True)
def shutdown(name, realm, seed, vmid):
r = vm_action("shutdown", OTPCredentials(name, realm, seed), vmid)
print(json.loads(r.content))

15
helper.py Normal file
View File

@ -0,0 +1,15 @@
import click
from dataclasses import dataclass
from pyotp import TOTP
@dataclass
class OTPCredentials:
name: str
realm: str
seed: str
def get_json(self):
r = {"name": self.name, "realm": self.realm, "token": TOTP(self.seed).now()}
return r

4
specs.json Normal file
View File

@ -0,0 +1,4 @@
{
"cpu": 2,
"ram": "2GB"
}

134
ucloud.py
View File

@ -1,127 +1,21 @@
import argparse import argparse
import requests import click
import json
from decouple import config from commands.vm import vm
from pyotp import TOTP from commands.user import user
from commands.host import host
def add_otp(parser): from commands.image import image
parser.add_argument("--name", required=True)
parser.add_argument("--realm", required=True)
parser.add_argument("--seed", required=True)
return parser
def add_vmid(parser):
parser.add_argument("--vmid", required=True)
return parser
argparser = argparse.ArgumentParser()
subparser = argparser.add_subparsers(dest="command")
create_image_parser = subparser.add_parser("create-image-from-file")
create_image_parser.add_argument("--uuid", required=True)
create_image_parser.add_argument("--name", required=True)
create_image_parser.add_argument("--image-store",
dest="image_store_name",
required=True)
images_parser = subparser.add_parser("images")
images_parser.add_argument("--list",
choices=["public", "private"],
required=True)
user_parser = subparser.add_parser("user")
user_subparser = user_parser.add_subparsers(dest="usercommand")
user_list_vms_parser = user_subparser.add_parser("list")
user_list_vms_parser.add_argument("--files", action='store_true')
user_list_vms_parser.add_argument("--vms", action='store_true')
add_otp(user_list_vms_parser)
vm_parser = subparser.add_parser("vm")
vm_subparser = vm_parser.add_subparsers(dest="vmcommand")
vm_create_parser = vm_subparser.add_parser("create")
add_otp(vm_create_parser)
vm_create_parser.add_argument("--specs_file", required=True)
vm_create_parser.add_argument("--image_uuid", required=True)
vm_start_parser = vm_subparser.add_parser("start") @click.group()
vm_suspend_parser = vm_subparser.add_parser("suspend") def entry_point():
vm_resume_parser = vm_subparser.add_parser("resume") pass
vm_shutdown_parser = vm_subparser.add_parser("shutdown")
vm_status_parser = vm_subparser.add_parser("status")
add_vmid(add_otp(vm_start_parser))
add_vmid(add_otp(vm_suspend_parser))
add_vmid(add_otp(vm_resume_parser))
add_vmid(add_otp(vm_shutdown_parser))
add_vmid(add_otp(vm_status_parser))
args = argparser.parse_args() entry_point.add_command(vm)
entry_point.add_command(user)
entry_point.add_command(image)
entry_point.add_command(host)
if args.command == "create-image-from-file": if __name__ == "__main__":
name = args.name entry_point()
uuid = args.uuid
image_store_name = args.image_store_name
data = {
"name": args.name,
"uuid": uuid,
"image_store": image_store_name
}
r = requests.post(f"{config('UCLOUD_API_SERVER')}/image/create", data)
print(r.content.decode("utf-8"))
elif args.command == "images":
if args.list == "public":
r = requests.get(f"{config('UCLOUD_API_SERVER')}/image/list-public")
print(json.loads(r.content))
elif args.command == "vm":
if args.vmcommand == "create":
with open(args.specs_file, "r") as specs_f:
specs = json.loads(specs_f.read())
data = {
"name": args.name,
"realm": args.realm,
"token": TOTP(args.seed).now(),
"specs": specs,
"image_uuid": args.image_uuid
}
r = requests.post(f"{config('UCLOUD_API_SERVER')}/vm/create",
json=data)
print(json.loads(r.content))
elif args.vmcommand in ["start", "suspend", "resume",
"status", "shutdown"]:
data = {
"name": args.name,
"realm": args.realm,
"token": TOTP(args.seed).now(),
"vmid": args.vmid,
}
if args.vmcommand == "status":
r = requests.get(f"{config('UCLOUD_API_SERVER')}/vm/{args.vmcommand}", json=data)
else:
r = requests.post(f"{config('UCLOUD_API_SERVER')}/vm/{args.vmcommand}", json=data)
print(json.loads(r.content))
elif args.command == "user":
if args.usercommand == "list" and args.vms:
data = {
"name": args.name,
"realm": args.realm,
"token": TOTP(args.seed).now()
}
r = requests.get(f"{config('UCLOUD_API_SERVER')}/user/vms",
json=data)
print(json.loads(r.content))
elif args.usercommand == "list" and args.files:
data = {
"name": args.name,
"realm": args.realm,
"token": TOTP(args.seed).now()
}
r = requests.get(f"{config('UCLOUD_API_SERVER')}/user/files",
json=data)
print(json.loads(r.content))