blis-cloud-cli 0.1.1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- blis_cli/__init__.py +0 -0
- blis_cli/blis.py +67 -0
- blis_cli/commands/__init__.py +0 -0
- blis_cli/commands/docker.py +139 -0
- blis_cli/commands/domain.py +144 -0
- blis_cli/commands/install.py +92 -0
- blis_cli/commands/logs.py +73 -0
- blis_cli/commands/start.py +13 -0
- blis_cli/commands/status.py +78 -0
- blis_cli/commands/stop.py +18 -0
- blis_cli/commands/swap.py +50 -0
- blis_cli/commands/update.py +37 -0
- blis_cli/extra/docker-compose.yml +57 -0
- blis_cli/extra/dump-blis_12-202202091919.sql +1539 -0
- blis_cli/extra/dump-blis_127-202202091919.sql +1604 -0
- blis_cli/extra/dump-blis_revamp-20220704.sql +1644 -0
- blis_cli/extra/templates/Caddyfile.j2 +22 -0
- blis_cli/util/__init__.py +1 -0
- blis_cli/util/bash.py +25 -0
- blis_cli/util/caddy.py +63 -0
- blis_cli/util/config.py +159 -0
- blis_cli/util/docker_util.py +118 -0
- blis_cli/util/environment.py +35 -0
- blis_cli/util/packages.py +26 -0
- blis_cloud_cli-0.1.1.dist-info/LICENSE +21 -0
- blis_cloud_cli-0.1.1.dist-info/METADATA +31 -0
- blis_cloud_cli-0.1.1.dist-info/RECORD +29 -0
- blis_cloud_cli-0.1.1.dist-info/WHEEL +4 -0
- blis_cloud_cli-0.1.1.dist-info/entry_points.txt +3 -0
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# Do not edit this file by hand!
|
|
2
|
+
# This file is created and modified by the `blis` tool.
|
|
3
|
+
|
|
4
|
+
http:// {
|
|
5
|
+
reverse_proxy http://app:80 {
|
|
6
|
+
header_up X-Forwarded-Proto http
|
|
7
|
+
header_up X-Forwarded-Scheme http
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
{% for domain in domains %}
|
|
12
|
+
https://{{ domain }} {
|
|
13
|
+
reverse_proxy http://app:80 {
|
|
14
|
+
header_up X-Forwarded-Proto https
|
|
15
|
+
header_up X-Forwarded-Scheme https
|
|
16
|
+
header_up Origin https://{{ domain }}
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
{% endfor %}
|
|
20
|
+
|
|
21
|
+
# Refer to the Caddy docs for more information:
|
|
22
|
+
# https://caddyserver.com/docs/caddyfile
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
# util module
|
blis_cli/util/bash.py
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import click
|
|
2
|
+
import os
|
|
3
|
+
import sys
|
|
4
|
+
import subprocess
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
def run(command: str, root=False):
|
|
8
|
+
cmd = ["bash", "-c", command]
|
|
9
|
+
if root:
|
|
10
|
+
cmd = ["sudo"] + cmd
|
|
11
|
+
|
|
12
|
+
if "BLIS_DEBUG" in os.environ and os.environ["BLIS_DEBUG"] == "true":
|
|
13
|
+
click.echo("+ " + " ".join(cmd))
|
|
14
|
+
|
|
15
|
+
proc = subprocess.run(cmd, capture_output=True)
|
|
16
|
+
|
|
17
|
+
if proc.returncode == 0:
|
|
18
|
+
return str(proc.stdout, "utf-8"), None
|
|
19
|
+
else:
|
|
20
|
+
return str(proc.stdout, "utf-8"), str(proc.stderr, "utf-8")
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
def sudo(command: str):
|
|
24
|
+
use_sudo = os.geteuid() != 0
|
|
25
|
+
return run(command, root=use_sudo)
|
blis_cli/util/caddy.py
ADDED
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import click
|
|
2
|
+
from jinja2 import Environment, FileSystemLoader, select_autoescape
|
|
3
|
+
import os
|
|
4
|
+
import shutil
|
|
5
|
+
import subprocess
|
|
6
|
+
import re
|
|
7
|
+
|
|
8
|
+
from blis_cli.util import config
|
|
9
|
+
from blis_cli.util import docker_util
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
jinja2 = Environment(
|
|
13
|
+
loader=FileSystemLoader(f"{os.path.dirname(__file__)}/../extra/templates/"),
|
|
14
|
+
autoescape=select_autoescape(),
|
|
15
|
+
)
|
|
16
|
+
|
|
17
|
+
CADDY_STANZA_START = re.compile("^https://(.+) {\s?$")
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def caddyfile():
|
|
21
|
+
return os.path.join(config.basedir(), "Caddyfile")
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
def installed():
|
|
25
|
+
caddyfile_exists = os.path.exists(caddyfile())
|
|
26
|
+
caddy_stanza_present = config.compose_key("services.caddy")
|
|
27
|
+
return caddyfile_exists and (caddy_stanza_present is not None)
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
def install():
|
|
31
|
+
config.add_volume("caddy_data")
|
|
32
|
+
config.add_volume("caddy_config")
|
|
33
|
+
config.add_section_from_template("services.caddy")
|
|
34
|
+
config.remove_key("services.app.ports")
|
|
35
|
+
config.set_key("services.app.depends_on", ["db", "caddy"])
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
def set_domains(domains: list):
|
|
39
|
+
try:
|
|
40
|
+
template = jinja2.get_template("Caddyfile.j2")
|
|
41
|
+
rendered = template.render(domains=domains)
|
|
42
|
+
|
|
43
|
+
with open(os.path.join(config.basedir(), "Caddyfile"), "w") as f:
|
|
44
|
+
f.write(rendered)
|
|
45
|
+
return None
|
|
46
|
+
except Exception as e:
|
|
47
|
+
return e
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
def get_domains():
|
|
51
|
+
domains = []
|
|
52
|
+
try:
|
|
53
|
+
with open(os.path.join(config.basedir(), "Caddyfile"), "r") as f:
|
|
54
|
+
for line in f:
|
|
55
|
+
res = CADDY_STANZA_START.match(line)
|
|
56
|
+
if res:
|
|
57
|
+
domains.append(res.groups()[0])
|
|
58
|
+
except FileNotFoundError as e:
|
|
59
|
+
return []
|
|
60
|
+
except Exception as e:
|
|
61
|
+
click.secho("Error reading Caddyfile: " + e, fg="red")
|
|
62
|
+
return []
|
|
63
|
+
return domains
|
blis_cli/util/config.py
ADDED
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
import click
|
|
2
|
+
import os
|
|
3
|
+
import yaml
|
|
4
|
+
from yaml import SafeDumper
|
|
5
|
+
|
|
6
|
+
SafeDumper.add_representer(
|
|
7
|
+
type(None),
|
|
8
|
+
lambda dumper, value: dumper.represent_scalar("tag:yaml.org,2002:null", ""),
|
|
9
|
+
)
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
compose_file_disclaimer = """
|
|
13
|
+
#####
|
|
14
|
+
# This file is an example docker-compose file for deploying BLIS to a cloud provider
|
|
15
|
+
# This file is used as a template, but will be rewritten by the BLIS tool as necessary.
|
|
16
|
+
|
|
17
|
+
"""
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def basedir():
|
|
21
|
+
return os.path.expanduser("~/.blis")
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
def make_basedir():
|
|
25
|
+
if not os.path.exists(basedir()):
|
|
26
|
+
os.makedirs(basedir())
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
def compose_file():
|
|
30
|
+
return os.path.join(basedir(), "docker-compose.yml")
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
def validate_compose():
|
|
34
|
+
if not os.path.exists(compose_file()):
|
|
35
|
+
return False
|
|
36
|
+
|
|
37
|
+
dcmp = _open_compose()
|
|
38
|
+
if dcmp is None:
|
|
39
|
+
return False
|
|
40
|
+
|
|
41
|
+
if "name" not in dcmp:
|
|
42
|
+
click.echo("Missing 'name' in docker-compose.yml", err=True)
|
|
43
|
+
return False
|
|
44
|
+
|
|
45
|
+
return True
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
def _open_compose():
|
|
49
|
+
try:
|
|
50
|
+
with open(compose_file(), "r") as f:
|
|
51
|
+
return yaml.safe_load(f)
|
|
52
|
+
except FileNotFoundError:
|
|
53
|
+
return None
|
|
54
|
+
except yaml.YAMLError as e:
|
|
55
|
+
click.echo(e, err=True)
|
|
56
|
+
return None
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
def _save_compose(contents):
|
|
60
|
+
try:
|
|
61
|
+
with open(compose_file(), "w") as f:
|
|
62
|
+
f.write(compose_file_disclaimer)
|
|
63
|
+
yaml.safe_dump(contents, f)
|
|
64
|
+
except Exception as e:
|
|
65
|
+
click.secho(e, err=True)
|
|
66
|
+
return False
|
|
67
|
+
return True
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
def _load_template_yml():
|
|
71
|
+
try:
|
|
72
|
+
with open(f"{os.path.dirname(__file__)}/../extra/docker-compose.yml", "r") as f:
|
|
73
|
+
return yaml.safe_load(f)
|
|
74
|
+
except Exception as e:
|
|
75
|
+
click.secho(e, err=True)
|
|
76
|
+
return None
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
def compose_key(key: str, contents=None):
|
|
80
|
+
if contents is None:
|
|
81
|
+
contents = _open_compose()
|
|
82
|
+
if contents is None:
|
|
83
|
+
return None
|
|
84
|
+
|
|
85
|
+
keys = key.split(".")
|
|
86
|
+
val = contents
|
|
87
|
+
for k in keys:
|
|
88
|
+
if k not in val:
|
|
89
|
+
return None
|
|
90
|
+
val = val[k]
|
|
91
|
+
|
|
92
|
+
return val
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
def add_volume(volname, opts=None):
|
|
96
|
+
if compose_key(f"volumes.{volname}"):
|
|
97
|
+
return False, "already exists"
|
|
98
|
+
|
|
99
|
+
contents = _open_compose()
|
|
100
|
+
contents["volumes"][volname] = opts
|
|
101
|
+
_save_compose(contents)
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
def add_section_from_template(keyname: str):
|
|
105
|
+
template_section = compose_key(keyname, _load_template_yml())
|
|
106
|
+
contents = _open_compose()
|
|
107
|
+
|
|
108
|
+
keys = keyname.split(".")
|
|
109
|
+
last = keys.pop()
|
|
110
|
+
|
|
111
|
+
val = contents
|
|
112
|
+
for k in keys:
|
|
113
|
+
if k not in val:
|
|
114
|
+
return False
|
|
115
|
+
val = val[k]
|
|
116
|
+
|
|
117
|
+
val[last] = template_section
|
|
118
|
+
|
|
119
|
+
_save_compose(contents)
|
|
120
|
+
|
|
121
|
+
return True
|
|
122
|
+
|
|
123
|
+
|
|
124
|
+
def remove_key(keyname):
|
|
125
|
+
contents = _open_compose()
|
|
126
|
+
|
|
127
|
+
keys = keyname.split(".")
|
|
128
|
+
last = keys.pop()
|
|
129
|
+
|
|
130
|
+
val = contents
|
|
131
|
+
for k in keys:
|
|
132
|
+
if k not in val:
|
|
133
|
+
return False
|
|
134
|
+
val = val[k]
|
|
135
|
+
|
|
136
|
+
val.pop(last, None)
|
|
137
|
+
|
|
138
|
+
_save_compose(contents)
|
|
139
|
+
|
|
140
|
+
return True
|
|
141
|
+
|
|
142
|
+
|
|
143
|
+
def set_key(keyname, value):
|
|
144
|
+
contents = _open_compose()
|
|
145
|
+
|
|
146
|
+
keys = keyname.split(".")
|
|
147
|
+
last = keys.pop()
|
|
148
|
+
|
|
149
|
+
val = contents
|
|
150
|
+
for k in keys:
|
|
151
|
+
if k not in val:
|
|
152
|
+
return False
|
|
153
|
+
val = val[k]
|
|
154
|
+
|
|
155
|
+
val[last] = value
|
|
156
|
+
|
|
157
|
+
_save_compose(contents)
|
|
158
|
+
|
|
159
|
+
return True
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
import click
|
|
2
|
+
import docker
|
|
3
|
+
import shutil
|
|
4
|
+
import subprocess
|
|
5
|
+
|
|
6
|
+
from blis_cli.util import bash
|
|
7
|
+
from blis_cli.util import caddy
|
|
8
|
+
from blis_cli.util import config
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def installed():
|
|
12
|
+
return shutil.which("docker") is not None
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def compose_v1_installed():
|
|
16
|
+
if not installed():
|
|
17
|
+
return False
|
|
18
|
+
return shutil.which("docker-compose") is not None
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def compose_v2_installed():
|
|
22
|
+
if not installed():
|
|
23
|
+
return False
|
|
24
|
+
res = subprocess.run(["docker", "compose"], capture_output=True)
|
|
25
|
+
return res.returncode == 0
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
def compose():
|
|
29
|
+
if compose_v2_installed():
|
|
30
|
+
return "docker compose"
|
|
31
|
+
elif compose_v1_installed():
|
|
32
|
+
return "docker-compose"
|
|
33
|
+
else:
|
|
34
|
+
return None
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
# Finds the _first_ container running the BLIS image.
|
|
38
|
+
def blis_container(client=None):
|
|
39
|
+
try:
|
|
40
|
+
client = client or docker.from_env()
|
|
41
|
+
img_tag = config.compose_key("services.app.image")
|
|
42
|
+
for container in client.containers.list():
|
|
43
|
+
if img_tag in container.image.tags:
|
|
44
|
+
return container
|
|
45
|
+
except Exception as e:
|
|
46
|
+
return None
|
|
47
|
+
return None
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
def blis_is_running():
|
|
51
|
+
return blis_container() is not None
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
def stop_blis_with_confirm():
|
|
55
|
+
click.secho(
|
|
56
|
+
"BLIS must be stopped in order to continue.",
|
|
57
|
+
fg="yellow",
|
|
58
|
+
)
|
|
59
|
+
if not click.confirm("Continue stopping BLIS?"):
|
|
60
|
+
return False
|
|
61
|
+
click.echo("Stopping BLIS... ", nl=False)
|
|
62
|
+
blis_container().stop()
|
|
63
|
+
click.secho("Success!", fg="green")
|
|
64
|
+
return True
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
# Starts BLIS containers
|
|
68
|
+
# Starting only "app" will ensure that all of the containers will come up at once.
|
|
69
|
+
# 'containers' can be specified to start containers in a certain order (if possible)
|
|
70
|
+
def start_blis(*containers):
|
|
71
|
+
if not containers or len(containers) == 0:
|
|
72
|
+
containers = ["db", "app"]
|
|
73
|
+
|
|
74
|
+
for container in containers:
|
|
75
|
+
click.echo(f"Starting BLIS {container}... ", nl=False)
|
|
76
|
+
out, err = bash.run(
|
|
77
|
+
f"{compose()} -f {config.compose_file()} up -d --wait {container}"
|
|
78
|
+
)
|
|
79
|
+
if err:
|
|
80
|
+
click.secho("Failed", fg="red")
|
|
81
|
+
click.echo(err, err=True)
|
|
82
|
+
return 1
|
|
83
|
+
else:
|
|
84
|
+
click.secho("Success!", fg="green")
|
|
85
|
+
|
|
86
|
+
return 0
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
def restart_caddy():
|
|
90
|
+
if not caddy.installed():
|
|
91
|
+
return
|
|
92
|
+
|
|
93
|
+
click.echo(f"Restarting Caddy... ", nl=False)
|
|
94
|
+
|
|
95
|
+
caddy_container = None
|
|
96
|
+
|
|
97
|
+
try:
|
|
98
|
+
client = docker.from_env()
|
|
99
|
+
img_tag = config.compose_key("services.caddy.image")
|
|
100
|
+
for container in client.containers.list():
|
|
101
|
+
if img_tag in container.image.tags:
|
|
102
|
+
caddy_container = container
|
|
103
|
+
break
|
|
104
|
+
except Exception as e:
|
|
105
|
+
click.secho("Failed", fg="red")
|
|
106
|
+
click.echo(e, err=True)
|
|
107
|
+
return 1
|
|
108
|
+
|
|
109
|
+
if caddy_container is not None:
|
|
110
|
+
out, err = bash.run(
|
|
111
|
+
f"{compose()} -f {config.compose_file()} restart caddy"
|
|
112
|
+
)
|
|
113
|
+
if err:
|
|
114
|
+
click.secho("Failed", fg="red")
|
|
115
|
+
click.echo(err, err=True)
|
|
116
|
+
return 1
|
|
117
|
+
else:
|
|
118
|
+
click.secho("Success!", fg="green")
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import os
|
|
2
|
+
import subprocess
|
|
3
|
+
import pwd
|
|
4
|
+
import grp
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
def can_sudo():
|
|
8
|
+
result = subprocess.run(["sudo", "-n", "echo", "hello"], capture_output=True)
|
|
9
|
+
return result.returncode == 0 and result.stdout == b"hello\n"
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def distro():
|
|
13
|
+
result = subprocess.run(
|
|
14
|
+
["grep", "DISTRIB_CODENAME", "/etc/lsb-release"], capture_output=True
|
|
15
|
+
)
|
|
16
|
+
if result.returncode == 0:
|
|
17
|
+
return result.stdout.decode("utf-8").strip().split("=")[1]
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def user():
|
|
21
|
+
return pwd.getpwuid(os.getuid())[0]
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
def in_docker_grp():
|
|
25
|
+
try:
|
|
26
|
+
return user() in grp.getgrnam("docker")[3]
|
|
27
|
+
except KeyError:
|
|
28
|
+
return False
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
SUPPORTED_DISTROS = set(["focal", "jammy"])
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
def supported_distro():
|
|
35
|
+
return distro() in SUPPORTED_DISTROS
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import click
|
|
2
|
+
|
|
3
|
+
from blis_cli.util import bash
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
def apt_update():
|
|
7
|
+
return bash.sudo("DEBIAN_FRONTEND=noninteractive apt-get update")
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def install(packages: list):
|
|
11
|
+
click.echo(f"Installing packages: {', '.join(packages)}")
|
|
12
|
+
return bash.sudo(
|
|
13
|
+
f"DEBIAN_FRONTEND=noninteractive apt-get install -y {' '.join(packages)}"
|
|
14
|
+
)
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
def remove(packages: list):
|
|
18
|
+
click.echo(f"Removing packages: {', '.join(packages)}")
|
|
19
|
+
return bash.sudo(
|
|
20
|
+
f"DEBIAN_FRONTEND=noninteractive apt-get remove -y {' '.join(packages)}"
|
|
21
|
+
)
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
def is_installed(package: str):
|
|
25
|
+
_, err = bash.run(f"dpkg -s {package}")
|
|
26
|
+
return err == None
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2023 Mitchell Rysavy
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
Metadata-Version: 2.1
|
|
2
|
+
Name: blis-cloud-cli
|
|
3
|
+
Version: 0.1.1
|
|
4
|
+
Summary: Command-line tool for the BLIS web-based lab information system.
|
|
5
|
+
License: MIT
|
|
6
|
+
Author: Mitchell Rysavy
|
|
7
|
+
Author-email: mitchell.rysavy@gmail.com
|
|
8
|
+
Requires-Python: >=3.8,<4.0
|
|
9
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
10
|
+
Classifier: Programming Language :: Python :: 3
|
|
11
|
+
Classifier: Programming Language :: Python :: 3.8
|
|
12
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
13
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
16
|
+
Requires-Dist: Jinja2 (>=3.1.3,<3.2.0)
|
|
17
|
+
Requires-Dist: PyYAML (>=6.0.1,<6.1.0)
|
|
18
|
+
Requires-Dist: click (>=8.1.7,<8.2.0)
|
|
19
|
+
Requires-Dist: colorama (>=0.4.4,<0.5.0)
|
|
20
|
+
Requires-Dist: docker (>=6.1.3,<6.2.0)
|
|
21
|
+
Requires-Dist: psutil (>=5.9.0,<5.10.0)
|
|
22
|
+
Requires-Dist: requests (>=2.31.0,<2.32.0)
|
|
23
|
+
Description-Content-Type: text/markdown
|
|
24
|
+
|
|
25
|
+
# blis-cloud-cli
|
|
26
|
+
|
|
27
|
+
A tool for managing cloud installations of [BLIS](http://blis.cc.gatech.edu/index.php).
|
|
28
|
+
|
|
29
|
+
Documentation for the tool can be found on [the BLIS documentation website.](https://docs.c4gblis.org/)
|
|
30
|
+
You can view the original proposal for this tool [here](docs/proposal.md).
|
|
31
|
+
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
blis_cli/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
2
|
+
blis_cli/blis.py,sha256=WybYFyhMg_eYWSAw-bczZ_0ddFu1CTZD2jStzY41HT8,1530
|
|
3
|
+
blis_cli/commands/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
4
|
+
blis_cli/commands/docker.py,sha256=w5wM6iY7RCKTdzKRzcic7_PBT30PYdMbEPN2O8SWhio,4320
|
|
5
|
+
blis_cli/commands/domain.py,sha256=fr9QxI_cUeOR09qSjToAt1WdnYHjKn5p709_qB5WvNY,4071
|
|
6
|
+
blis_cli/commands/install.py,sha256=caj8L96VRwTLkRVb5EsXud6eWXVp7f0Eaa15_HLVF2k,2871
|
|
7
|
+
blis_cli/commands/logs.py,sha256=ZGJNiPf82wm4hKnCt5CG30R7pr5Yy_jw4dsrEVeadA8,1942
|
|
8
|
+
blis_cli/commands/start.py,sha256=6W-3xos-VFuafRKbJXg-oISDay93Qgj6bNfblqr-PcU,299
|
|
9
|
+
blis_cli/commands/status.py,sha256=bOermMJRJaXyhSCrGwChWsqUI_2k4JvlZj0vNCISeRs,2655
|
|
10
|
+
blis_cli/commands/stop.py,sha256=7eKBG2apw4bP1NHL6TBqkiwIx3jilF-PjuRkq7TsbAg,426
|
|
11
|
+
blis_cli/commands/swap.py,sha256=2QtxQPDYKJmLlPJbBMmxRQ1_Ua5wyTuOIx65_j7s_5M,1250
|
|
12
|
+
blis_cli/commands/update.py,sha256=OvgSzLEEMSUXzdQn0iuW8fMNvuWyfxeMrmhPDbqoDfo,961
|
|
13
|
+
blis_cli/extra/docker-compose.yml,sha256=YU-hBL5HBOOy8M4MdD22p1ZWL9wReawl2YkOsXHKlLE,1269
|
|
14
|
+
blis_cli/extra/dump-blis_12-202202091919.sql,sha256=Es151WVZK8Jh3In0cXx_4Y3JWD6lPcL34EtAAMOJvTE,77357
|
|
15
|
+
blis_cli/extra/dump-blis_127-202202091919.sql,sha256=rv05pRDOkS4kA_k3ya-dW9yjy4MvjJ25d28jY316QeE,2828964
|
|
16
|
+
blis_cli/extra/dump-blis_revamp-20220704.sql,sha256=Ca8aFLqfRfkUIHJfU16BHv5MPCrpFws2cP35-lkyPeM,45125
|
|
17
|
+
blis_cli/extra/templates/Caddyfile.j2,sha256=_dP4GVlCzoPabSOw9P9Gs_EE1bSIsmDIRx8c1UigYC0,517
|
|
18
|
+
blis_cli/util/__init__.py,sha256=gB924oIvkpDlCtZlR-ZKAbqWN8OXxjegQXH2L_big4Q,14
|
|
19
|
+
blis_cli/util/bash.py,sha256=miqq5I5xzLCW7OWjR0Gzrw_IJr8EPmjpvDPAPcRooDw,587
|
|
20
|
+
blis_cli/util/caddy.py,sha256=GTYInwwtyEjq3JJQDyiLWZHeJFQ8xdSp-Tk8djlO31I,1712
|
|
21
|
+
blis_cli/util/config.py,sha256=miDndLRZTBgFCOO6t6p5FK2VT_uuRmOWC23uPevPDUU,3188
|
|
22
|
+
blis_cli/util/docker_util.py,sha256=y-YUG0BmeQkjIKSr87pWW7idQXSNHmuJUUsloCUkzM8,3071
|
|
23
|
+
blis_cli/util/environment.py,sha256=_m2YdpzWOd3IzH8hQGd_DvUrz0NDDQ4EESWnR63DPWg,735
|
|
24
|
+
blis_cli/util/packages.py,sha256=WJhwaqzzHt4Wi34gkyQd7d1Xx0noqZIayL7h1xnBGD0,638
|
|
25
|
+
blis_cloud_cli-0.1.1.dist-info/LICENSE,sha256=Fg3Y31_4Bsd-dXMUibTrCrtmfYitWVqeuJhEd13t50s,1072
|
|
26
|
+
blis_cloud_cli-0.1.1.dist-info/METADATA,sha256=Lmm_fxSJFezTEGDl8nuFlqn1R7zUPah1TvcfJzTnHyM,1196
|
|
27
|
+
blis_cloud_cli-0.1.1.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
|
|
28
|
+
blis_cloud_cli-0.1.1.dist-info/entry_points.txt,sha256=lleshol3IILCEcRfKrYsk7nnyRN14zHKHyn9VMAPAKA,43
|
|
29
|
+
blis_cloud_cli-0.1.1.dist-info/RECORD,,
|