Merge branch 'wip' into 'master'

See merge request ucloud/ucloud-cli!2
This commit is contained in:
Ahmed Bilal 2019-11-11 19:49:35 +01:00
commit d1dd2839b7
9 changed files with 193 additions and 90 deletions

View file

@ -12,4 +12,4 @@ pyotp = "*"
click = "*" click = "*"
[requires] [requires]
python_version = "3.7" python_version = "3.5"

16
Pipfile.lock generated
View file

@ -1,11 +1,11 @@
{ {
"_meta": { "_meta": {
"hash": { "hash": {
"sha256": "1f6e0448a1e04906885393b4ff57423363593680a7b6f73a5ed1f514496bb1f3" "sha256": "ad97ea0bec676c536266766c718bd590b17e0e28d47728ab68cf21d09fbb07d4"
}, },
"pipfile-spec": 6, "pipfile-spec": 6,
"requires": { "requires": {
"python_version": "3.7" "python_version": "3.5"
}, },
"sources": [ "sources": [
{ {
@ -18,10 +18,10 @@
"default": { "default": {
"certifi": { "certifi": {
"hashes": [ "hashes": [
"sha256:046832c04d4e752f37383b628bc601a7ea7211496b4638f6514d0e5b9acc4939", "sha256:e4f3620cfea4f83eedc95b24abd9cd56f3c4b146dd0177e83a21b4eb49e21e50",
"sha256:945e3ba63a0b9f577b1395204e13c3a231f9bc0223888be653286534e5873695" "sha256:fd7c7c74727ddcf00e9acd26bba8da604ffec95bf1c2144e67aff7a8b50e6cef"
], ],
"version": "==2019.6.16" "version": "==2019.9.11"
}, },
"chardet": { "chardet": {
"hashes": [ "hashes": [
@ -47,11 +47,11 @@
}, },
"pyotp": { "pyotp": {
"hashes": [ "hashes": [
"sha256:1e3dc3d16919c4efac528d1dbecc17de1a97c4ecfdacb89d7726ed2c6645adff", "sha256:c88f37fd47541a580b744b42136f387cdad481b560ef410c0d85c957eb2a2bc0",
"sha256:be0ffeabddaa5ee53e7204e7740da842d070cf69168247a3d0c08541b84de602" "sha256:fc537e8acd985c5cbf51e11b7d53c42276fee017a73aec7c07380695671ca1a1"
], ],
"index": "pypi", "index": "pypi",
"version": "==2.2.7" "version": "==2.3.0"
}, },
"python-decouple": { "python-decouple": {
"hashes": [ "hashes": [

View file

@ -1,21 +1,20 @@
import click
import json import json
from dataclasses import dataclass
from pyotp import TOTP from pyotp import TOTP
@dataclass
class OTPCredentials: class OTPCredentials:
name: str def __init__(self, name, realm, seed):
realm: str self.name = name # type: str
seed: str self.realm = realm # type: str
self.seed = seed # type: str
def get_json(self): def get_json(self):
r = {"name": self.name, "realm": self.realm, "token": TOTP(self.seed).now()} return {"name": self.name, "realm": self.realm, "token": TOTP(self.seed).now()}
return r
def load_dump_pretty(content): def load_dump_pretty(content):
if isinstance(content, bytes):
content = content.decode("utf-8")
parsed = json.loads(content) parsed = json.loads(content)
return json.dumps(parsed, indent=4, sort_keys=True) return json.dumps(parsed, indent=4, sort_keys=True)

View file

@ -1,9 +1,10 @@
import click
import json import json
import requests
from commands.helper import OTPCredentials, load_dump_pretty
from decouple import config from decouple import config
from .helper import OTPCredentials, load_dump_pretty
import click
import requests
@click.group() @click.group()
@ -11,25 +12,30 @@ def host():
pass pass
@host.command("add") @host.command("create")
@click.option("--name", envvar="OTP_NAME", required=True) @click.option("--name", envvar="OTP_NAME", required=True)
@click.option("--realm", envvar="OTP_REALM", required=True) @click.option("--realm", envvar="OTP_REALM", required=True)
@click.option("--seed", envvar="OTP_SEED", required=True) @click.option("--seed", envvar="OTP_SEED", required=True)
@click.option("--specs", required=True)
@click.option("--hostname", required=True) @click.option("--hostname", required=True)
def add_host(name, realm, seed, specs, hostname): @click.option("--cpu", required=True, type=int)
with open(specs, "r") as specs_f: @click.option("--ram", required=True)
specs = json.loads(specs_f.read()) @click.option("--os-ssd", required=True)
data = { @click.option("--hdd", default=list(), multiple=True)
**OTPCredentials(name, realm, seed).get_json(), def create(name, realm, seed, hostname, cpu, ram, os_ssd, hdd):
"specs": specs, data = {
"hostname": hostname, **OTPCredentials(name, realm, seed).get_json(),
} "hostname": hostname,
r = requests.post(f"{config('UCLOUD_API_SERVER')}/host/create", json=data) "specs": {
print(load_dump_pretty(r.content)) 'cpu': cpu,
'ram': ram,
'os-ssd': os_ssd,
'hdd': hdd
},
}
r = requests.post("{}/host/create".format(config('UCLOUD_API_SERVER')), json=data)
print(load_dump_pretty(r.content))
@host.command("list") @host.command("list")
def list_host(): def list_host():
r = requests.get(f"{config('UCLOUD_API_SERVER')}/host/list") r = requests.get("{}/host/list".format(config('UCLOUD_API_SERVER')))
print(load_dump_pretty(r.content)) print(load_dump_pretty(r.content))

View file

@ -1,10 +1,8 @@
import click from commands.helper import load_dump_pretty
import json
import requests
from decouple import config from decouple import config
from .helper import OTPCredentials, load_dump_pretty
import click
import requests
@click.group() @click.group()
def image(): def image():
@ -16,15 +14,15 @@ def image():
@click.option("--private", is_flag=True) @click.option("--private", is_flag=True)
def _list(public, private): def _list(public, private):
if public: if public:
r = requests.get(f"{config('UCLOUD_API_SERVER')}/image/list-public") r = requests.get("{}/image/list-public".format(config('UCLOUD_API_SERVER')))
print(load_dump_pretty(r.content)) print(load_dump_pretty(r.content))
@image.command("create-from-file") @image.command("create-from-file")
@click.option("--name", required=True) @click.option("--name", required=True)
@click.option("--uuid", required=True) @click.option("--uuid", required=True)
@click.option("--image_store_name", required=True) @click.option("--image-store-name", required=True)
def create_from_file(name, uuid, image_store_name): def create_from_file(name, uuid, image_store_name):
data = {"name": name, "uuid": uuid, "image_store": image_store_name} data = {"name": name, "uuid": uuid, "image_store": image_store_name}
r = requests.post(f"{config('UCLOUD_API_SERVER')}/image/create", json=data) r = requests.post("{}/image/create".format(config('UCLOUD_API_SERVER')), json=data)
print(load_dump_pretty(r.content)) print(load_dump_pretty(r.content))

25
commands/network.py Normal file
View file

@ -0,0 +1,25 @@
from commands.helper import load_dump_pretty, OTPCredentials
from decouple import config
import click
import requests
@click.group()
def network():
pass
@network.command("create")
@click.option("--name", envvar="OTP_NAME", required=True)
@click.option("--realm", envvar="OTP_REALM", required=True)
@click.option("--seed", envvar="OTP_SEED", required=True)
@click.option("--network-name", required=True)
@click.option("--network-type", required=True)
def create(name, realm, seed, network_name, network_type):
data = {
**OTPCredentials(name, realm, seed).get_json(),
"network_name": network_name,
"type": network_type
}
r = requests.post("{}/network/create".format(config('UCLOUD_API_SERVER')), json=data)
print(load_dump_pretty(r.content))

View file

@ -1,9 +1,8 @@
import click from commands.helper import OTPCredentials, load_dump_pretty
import json
import requests
from decouple import config from decouple import config
from .helper import OTPCredentials, load_dump_pretty
import click
import requests
@click.group() @click.group()
@ -17,7 +16,7 @@ def user():
@click.option("--seed", envvar="OTP_SEED", required=True) @click.option("--seed", envvar="OTP_SEED", required=True)
def list_files(name, realm, seed): def list_files(name, realm, seed):
data = OTPCredentials(name, realm, seed).get_json() data = OTPCredentials(name, realm, seed).get_json()
r = requests.get(f"{config('UCLOUD_API_SERVER')}/user/files", json=data) r = requests.get("{}/user/files".format(config('UCLOUD_API_SERVER')), json=data)
print(load_dump_pretty(r.content)) print(load_dump_pretty(r.content))
@ -27,5 +26,61 @@ def list_files(name, realm, seed):
@click.option("--seed", envvar="OTP_SEED", required=True) @click.option("--seed", envvar="OTP_SEED", required=True)
def list_vms(name, realm, seed): def list_vms(name, realm, seed):
data = OTPCredentials(name, realm, seed).get_json() data = OTPCredentials(name, realm, seed).get_json()
r = requests.get(f"{config('UCLOUD_API_SERVER')}/user/vms", json=data) r = requests.get("{}/user/vms".format(config('UCLOUD_API_SERVER')), json=data)
print(load_dump_pretty(r.content))
@user.command("network")
@click.option("--name", envvar="OTP_NAME", required=True)
@click.option("--realm", envvar="OTP_REALM", required=True)
@click.option("--seed", envvar="OTP_SEED", required=True)
def list_files(name, realm, seed):
data = OTPCredentials(name, realm, seed).get_json()
r = requests.get("{}/user/networks".format(config('UCLOUD_API_SERVER')), json=data)
print(load_dump_pretty(r.content))
@user.command("add-ssh")
@click.option("--name", envvar="OTP_NAME", required=True)
@click.option("--realm", envvar="OTP_REALM", required=True)
@click.option("--seed", envvar="OTP_SEED", required=True)
@click.option("--key-name", required=True)
@click.option("--key", required=True)
def add_ssh(name, realm, seed, key_name, key):
otp = OTPCredentials(name, realm, seed)
data = {
**otp.get_json(),
"key_name": key_name,
"key": key
}
r = requests.post("{}/user/add-ssh".format(config('UCLOUD_API_SERVER')), json=data)
print(load_dump_pretty(r.content))
@user.command("remove-ssh")
@click.option("--name", envvar="OTP_NAME", required=True)
@click.option("--realm", envvar="OTP_REALM", required=True)
@click.option("--seed", envvar="OTP_SEED", required=True)
@click.option("--key-name", required=True)
def remove_ssh(name, realm, seed, key_name):
otp = OTPCredentials(name, realm, seed)
data = {
**otp.get_json(),
"key_name": key_name,
}
r = requests.get("{}/user/remove-ssh".format(config('UCLOUD_API_SERVER')), json=data)
print(load_dump_pretty(r.content))
@user.command("get-ssh")
@click.option("--name", envvar="OTP_NAME", required=True)
@click.option("--realm", envvar="OTP_REALM", required=True)
@click.option("--seed", envvar="OTP_SEED", required=True)
@click.option("--key-name", default="")
def add_ssh(name, realm, seed, key_name):
otp = OTPCredentials(name, realm, seed)
data = {
**otp.get_json(),
"key_name": key_name,
}
r = requests.get("{}/user/get-ssh".format(config('UCLOUD_API_SERVER')), json=data)
print(load_dump_pretty(r.content)) print(load_dump_pretty(r.content))

View file

@ -1,14 +1,15 @@
import click
import json import json
from commands.helper import OTPCredentials, load_dump_pretty
from decouple import config
import click
import requests import requests
from decouple import config
from .helper import OTPCredentials, load_dump_pretty
def vm_command(command, otp, vm_name, **kwargs):
def vm_command(command, otp, uuid): data = {**otp.get_json(), "vm_name": vm_name, "action": command, **kwargs}
data = {**otp.get_json(), "uuid": uuid, "action": command} r = requests.post("{}/vm/action".format(config('UCLOUD_API_SERVER')), json=data)
r = requests.post(f"{config('UCLOUD_API_SERVER')}/vm/action", json=data)
return r return r
@ -21,27 +22,38 @@ def vm():
@click.option("--name", envvar="OTP_NAME", required=True) @click.option("--name", envvar="OTP_NAME", required=True)
@click.option("--realm", envvar="OTP_REALM", required=True) @click.option("--realm", envvar="OTP_REALM", required=True)
@click.option("--seed", envvar="OTP_SEED", required=True) @click.option("--seed", envvar="OTP_SEED", required=True)
@click.option("--specs", required=True) @click.option("--vm-name", required=True)
@click.option("--image_uuid", required=True) @click.option("--cpu", required=True, type=int)
def create(name, realm, seed, specs, image_uuid): @click.option("--ram", required=True)
with open(specs, "r") as specs_f: @click.option("--os-ssd", required=True)
specs = json.loads(specs_f.read()) @click.option("--hdd", default=list(), multiple=True)
data = { @click.option("--image", required=True)
**OTPCredentials(name, realm, seed).get_json(), @click.option("--network", default=list(), multiple=True)
"specs": specs, def create(name, realm, seed, vm_name, cpu, ram, os_ssd, hdd, image, network):
"image_uuid": image_uuid, data = {
} **OTPCredentials(name, realm, seed).get_json(),
r = requests.post(f"{config('UCLOUD_API_SERVER')}/vm/create", json=data) "vm_name": vm_name,
print(load_dump_pretty(r.content)) "specs": {
'cpu': cpu,
'ram': ram,
'os-ssd': os_ssd,
'hdd': hdd
},
"network": network,
"image": image,
}
r = requests.post("{}/vm/create".format(config('UCLOUD_API_SERVER')), json=data)
print(load_dump_pretty(r.content))
@vm.command("start") @vm.command("start")
@click.option("--name", envvar="OTP_NAME", required=True) @click.option("--name", envvar="OTP_NAME", required=True)
@click.option("--realm", envvar="OTP_REALM", required=True) @click.option("--realm", envvar="OTP_REALM", required=True)
@click.option("--seed", envvar="OTP_SEED", required=True) @click.option("--seed", envvar="OTP_SEED", required=True)
@click.option("--uuid", required=True) @click.option("--vm-name", required=True)
def start(name, realm, seed, uuid): @click.option("--in_support_of")
r = vm_command("start", OTPCredentials(name, realm, seed), uuid) def start(name, realm, seed, vm_name, in_support_of):
r = vm_command("start", OTPCredentials(name, realm, seed), vm_name, in_support_of=in_support_of)
print(load_dump_pretty(r.content)) print(load_dump_pretty(r.content))
@ -49,9 +61,10 @@ def start(name, realm, seed, uuid):
@click.option("--name", envvar="OTP_NAME", required=True) @click.option("--name", envvar="OTP_NAME", required=True)
@click.option("--realm", envvar="OTP_REALM", required=True) @click.option("--realm", envvar="OTP_REALM", required=True)
@click.option("--seed", envvar="OTP_SEED", required=True) @click.option("--seed", envvar="OTP_SEED", required=True)
@click.option("--uuid", required=True) @click.option("--vm-name", required=True)
def stop(name, realm, seed, uuid): @click.option("--in_support_of")
r = vm_command("stop", OTPCredentials(name, realm, seed), uuid) def stop(name, realm, seed, vm_name, in_support_of):
r = vm_command("stop", OTPCredentials(name, realm, seed), vm_name, in_support_of=in_support_of)
print(load_dump_pretty(r.content)) print(load_dump_pretty(r.content))
@ -59,9 +72,10 @@ def stop(name, realm, seed, uuid):
@click.option("--name", envvar="OTP_NAME", required=True) @click.option("--name", envvar="OTP_NAME", required=True)
@click.option("--realm", envvar="OTP_REALM", required=True) @click.option("--realm", envvar="OTP_REALM", required=True)
@click.option("--seed", envvar="OTP_SEED", required=True) @click.option("--seed", envvar="OTP_SEED", required=True)
@click.option("--uuid", required=True) @click.option("--vm-name", required=True)
def delete(name, realm, seed, uuid): @click.option("--in_support_of")
r = vm_command("delete", OTPCredentials(name, realm, seed), uuid) def delete(name, realm, seed, vm_name, in_support_of):
r = vm_command("delete", OTPCredentials(name, realm, seed), vm_name, in_support_of=in_support_of)
print(load_dump_pretty(r.content)) print(load_dump_pretty(r.content))
@ -69,24 +83,29 @@ def delete(name, realm, seed, uuid):
@click.option("--name", envvar="OTP_NAME", required=True) @click.option("--name", envvar="OTP_NAME", required=True)
@click.option("--realm", envvar="OTP_REALM", required=True) @click.option("--realm", envvar="OTP_REALM", required=True)
@click.option("--seed", envvar="OTP_SEED", required=True) @click.option("--seed", envvar="OTP_SEED", required=True)
@click.option("--uuid", required=True) @click.option("--vm-name", required=True)
def status(name, realm, seed, uuid): @click.option("--in_support_of")
data = {"name": name, "realm": realm, "seed": seed, "uuid": uuid} def status(name, realm, seed, vm_name, in_support_of):
r = requests.get(f"{config('UCLOUD_API_SERVER')}/vm/status", json=data) otp = OTPCredentials(name, realm, seed)
data = {**otp.get_json(), "vm_name": vm_name, "in_support_of": in_support_of}
r = requests.get("{}/vm/status".format(config('UCLOUD_API_SERVER')), json=data)
print(load_dump_pretty(r.content)) print(load_dump_pretty(r.content))
@vm.command("migrate") @vm.command("migrate")
@click.option("--name", envvar="OTP_NAME", required=True) @click.option("--name", envvar="OTP_NAME", required=True)
@click.option("--realm", envvar="OTP_REALM", required=True) @click.option("--realm", envvar="OTP_REALM", required=True)
@click.option("--seed", envvar="OTP_SEED", required=True) @click.option("--seed", envvar="OTP_SEED", required=True)
@click.option("--uuid", required=True) @click.option("--vm-name", required=True)
@click.option("--destination", required=True) @click.option("--destination", required=True)
def vm_migration(name, realm, seed, uuid, destination): @click.option("--in_support_of")
def vm_migration(name, realm, seed, vm_name, destination, in_support_of):
otp = OTPCredentials(name, realm, seed) otp = OTPCredentials(name, realm, seed)
data = { data = {
**otp.get_json(), **otp.get_json(),
"uuid": uuid, "vm_name": vm_name,
"destination": destination "destination": destination,
"in_support_of": in_support_of,
} }
r = requests.post(f"{config('UCLOUD_API_SERVER')}/vm/migrate", json=data) r = requests.post("{}/vm/migrate".format(config('UCLOUD_API_SERVER')), json=data)
print(load_dump_pretty(r.content)) print(load_dump_pretty(r.content))

View file

@ -4,7 +4,7 @@ from commands.vm import vm
from commands.user import user from commands.user import user
from commands.host import host from commands.host import host
from commands.image import image from commands.image import image
from commands.network import network
@click.group() @click.group()
def entry_point(): def entry_point():
@ -15,6 +15,7 @@ entry_point.add_command(vm)
entry_point.add_command(user) entry_point.add_command(user)
entry_point.add_command(image) entry_point.add_command(image)
entry_point.add_command(host) entry_point.add_command(host)
entry_point.add_command(network)
if __name__ == "__main__": if __name__ == "__main__":
entry_point() entry_point()