fine-tuning and starting to work on account-balance
This commit is contained in:
parent
a6e655ef72
commit
d7ddf37cfa
@ -1,5 +1,6 @@
|
|||||||
import re
|
import re
|
||||||
import sys
|
import sys
|
||||||
|
from datetime import datetime
|
||||||
from flask import Blueprint
|
from flask import Blueprint
|
||||||
from flask import flash
|
from flask import flash
|
||||||
from flask import current_app
|
from flask import current_app
|
||||||
@ -23,16 +24,16 @@ def makeCapsulId():
|
|||||||
lettersAndNumbers = generate(alphabet="1234567890qwertyuiopasdfghjklzxcvbnm", size=10)
|
lettersAndNumbers = generate(alphabet="1234567890qwertyuiopasdfghjklzxcvbnm", size=10)
|
||||||
return f"capsul-{lettersAndNumbers}"
|
return f"capsul-{lettersAndNumbers}"
|
||||||
|
|
||||||
def double_check_capsul_address(db_model, email, id, ipv4):
|
def double_check_capsul_address(id, ipv4):
|
||||||
try:
|
try:
|
||||||
result = current_app.config["VIRTUALIZATION_MODEL"].get(id)
|
result = current_app.config["VIRTUALIZATION_MODEL"].get(id)
|
||||||
if result.ipv4 != ipv4:
|
if result.ipv4 != ipv4:
|
||||||
ipv4 = result.ipv4
|
ipv4 = result.ipv4
|
||||||
db_model.updateVm(email=email, id=id, ipv4=result.ipv4)
|
get_model().updateVm(email=session["account"], id=id, ipv4=result.ipv4)
|
||||||
except:
|
except:
|
||||||
print(f"""
|
print(f"""
|
||||||
error occurred in list capsuls endpoint while trying to grab ip address of {vm['id']}
|
the virtualization model threw an error in double_check_capsul_address of {id}:
|
||||||
via the virtualization model: {my_exec_info_message(sys.exc_info())}"""
|
{my_exec_info_message(sys.exc_info())}"""
|
||||||
)
|
)
|
||||||
|
|
||||||
return ipv4
|
return ipv4
|
||||||
@ -40,13 +41,12 @@ def double_check_capsul_address(db_model, email, id, ipv4):
|
|||||||
@bp.route("/")
|
@bp.route("/")
|
||||||
@account_required
|
@account_required
|
||||||
def index():
|
def index():
|
||||||
db_model = get_model()
|
vms = get_vms()
|
||||||
vms = db_model.list_vms_for_account(email=session["account"])
|
|
||||||
|
|
||||||
# for now we are going to check the IP according to the virt model
|
# for now we are going to check the IP according to the virt model
|
||||||
# on every request. this could be done by a background job and cached later on...
|
# on every request. this could be done by a background job and cached later on...
|
||||||
for vm in vms:
|
for vm in vms:
|
||||||
vm["ipv4"] = double_check_capsul_address(db_model, session["account"], vm["id"], vm["ipv4"])
|
vm["ipv4"] = double_check_capsul_address(vm["id"], vm["ipv4"])
|
||||||
|
|
||||||
vms = list(map(
|
vms = list(map(
|
||||||
lambda x: dict(
|
lambda x: dict(
|
||||||
@ -65,13 +65,12 @@ def index():
|
|||||||
@bp.route("/<string:id>")
|
@bp.route("/<string:id>")
|
||||||
@account_required
|
@account_required
|
||||||
def detail(id):
|
def detail(id):
|
||||||
db_model = get_model()
|
vm = get_model().get_vm_detail(email=session["account"], id=id)
|
||||||
vm = db_model.get_vm_detail(email=session["account"], id=id)
|
|
||||||
|
|
||||||
if vm is None:
|
if vm is None:
|
||||||
return abort(404, f"{id} doesn't exist.")
|
return abort(404, f"{id} doesn't exist.")
|
||||||
|
|
||||||
vm["ipv4"] = double_check_capsul_address(db_model, session["account"], vm["id"], vm["ipv4"])
|
vm["ipv4"] = double_check_capsul_address(vm["id"], vm["ipv4"])
|
||||||
vm["created"] = vm['created'].strftime("%b %d %Y %H:%M")
|
vm["created"] = vm['created'].strftime("%b %d %Y %H:%M")
|
||||||
vm["ssh_public_keys"] = ", ".join(vm["ssh_public_keys"]) if len(vm["ssh_public_keys"]) > 0 else "<deleted>"
|
vm["ssh_public_keys"] = ", ".join(vm["ssh_public_keys"]) if len(vm["ssh_public_keys"]) > 0 else "<deleted>"
|
||||||
|
|
||||||
@ -81,10 +80,9 @@ def detail(id):
|
|||||||
@bp.route("/create", methods=("GET", "POST"))
|
@bp.route("/create", methods=("GET", "POST"))
|
||||||
@account_required
|
@account_required
|
||||||
def create():
|
def create():
|
||||||
db_model = get_model()
|
vm_sizes = get_model().vm_sizes_dict()
|
||||||
vm_sizes = db_model.vm_sizes_dict()
|
operating_systems = get_model().operating_systems_dict()
|
||||||
operating_systems = db_model.operating_systems_dict()
|
ssh_public_keys = get_model().list_ssh_public_keys_for_account(session["account"])
|
||||||
ssh_public_keys = db_model.list_ssh_public_keys_for_account(session["account"])
|
|
||||||
errors = list()
|
errors = list()
|
||||||
created_os = None
|
created_os = None
|
||||||
|
|
||||||
@ -125,7 +123,7 @@ def create():
|
|||||||
|
|
||||||
if len(errors) == 0:
|
if len(errors) == 0:
|
||||||
id = makeCapsulId()
|
id = makeCapsulId()
|
||||||
db_model.create_vm(
|
get_model().create_vm(
|
||||||
email=session["account"],
|
email=session["account"],
|
||||||
id=id,
|
id=id,
|
||||||
size=size,
|
size=size,
|
||||||
@ -158,7 +156,6 @@ def create():
|
|||||||
@bp.route("/ssh", methods=("GET", "POST"))
|
@bp.route("/ssh", methods=("GET", "POST"))
|
||||||
@account_required
|
@account_required
|
||||||
def ssh_public_keys():
|
def ssh_public_keys():
|
||||||
db_model = get_model()
|
|
||||||
errors = list()
|
errors = list()
|
||||||
|
|
||||||
if request.method == "POST":
|
if request.method == "POST":
|
||||||
@ -179,29 +176,58 @@ def ssh_public_keys():
|
|||||||
if not re.match(r"^(ssh|ecdsa)-[0-9A-Za-z+/_=@. -]+$", content):
|
if not re.match(r"^(ssh|ecdsa)-[0-9A-Za-z+/_=@. -]+$", content):
|
||||||
errors.append("Content must match \"^(ssh|ecdsa)-[0-9A-Za-z+/_=@. -]+$\"")
|
errors.append("Content must match \"^(ssh|ecdsa)-[0-9A-Za-z+/_=@. -]+$\"")
|
||||||
|
|
||||||
if db_model.ssh_public_key_name_exists(session["account"], name):
|
if get_model().ssh_public_key_name_exists(session["account"], name):
|
||||||
errors.append("A key with that name already exists")
|
errors.append("A key with that name already exists")
|
||||||
|
|
||||||
if len(errors) == 0:
|
if len(errors) == 0:
|
||||||
db_model.create_ssh_public_key(session["account"], name, content)
|
get_model().create_ssh_public_key(session["account"], name, content)
|
||||||
|
|
||||||
elif method == "DELETE":
|
elif method == "DELETE":
|
||||||
|
|
||||||
if len(errors) == 0:
|
if len(errors) == 0:
|
||||||
db_model.delete_ssh_public_key(session["account"], name)
|
get_model().delete_ssh_public_key(session["account"], name)
|
||||||
|
|
||||||
for error in errors:
|
for error in errors:
|
||||||
flash(error)
|
flash(error)
|
||||||
|
|
||||||
keys_list=list(map(
|
keys_list=list(map(
|
||||||
lambda x: dict(name=x['name'], content=f"{x['content'][:20]}...{x['content'][len(x['content'])-20:]}"),
|
lambda x: dict(name=x['name'], content=f"{x['content'][:20]}...{x['content'][len(x['content'])-20:]}"),
|
||||||
db_model.list_ssh_public_keys_for_account(session["account"])
|
get_model().list_ssh_public_keys_for_account(session["account"])
|
||||||
))
|
))
|
||||||
|
|
||||||
return render_template("ssh-public-keys.html", ssh_public_keys=keys_list, has_ssh_public_keys=len(keys_list) > 0)
|
return render_template("ssh-public-keys.html", ssh_public_keys=keys_list, has_ssh_public_keys=len(keys_list) > 0)
|
||||||
|
|
||||||
|
def get_vms():
|
||||||
|
if 'user_vms' not in g:
|
||||||
|
g.user_vms = get_model().list_vms_for_account(session["account"])
|
||||||
|
return g.user_vms
|
||||||
|
|
||||||
@bp.route("/billing")
|
def get_payments():
|
||||||
|
if 'user_payments' not in g:
|
||||||
|
g.user_payments = get_model().list_payments_for_account(session["account"])
|
||||||
|
return g.user_payments
|
||||||
|
|
||||||
|
def get_account_balance():
|
||||||
|
|
||||||
|
|
||||||
|
average_number_of_days_in_a_month = 30.44
|
||||||
|
|
||||||
|
vm_cost_dollars = 0.0
|
||||||
|
for vm in get_vms():
|
||||||
|
end_datetime = vm["deleted"] if vm["deleted"] else datetime.now()
|
||||||
|
vm_months = ( end_datetime - vm["created"] ).days / average_number_of_days_in_a_month
|
||||||
|
vm_cost_dollars += vm_months * vm["dollars_per_month"]
|
||||||
|
|
||||||
|
payment_total = sum(map(lambda x: x["dollars"], get_payments()))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@bp.route("/account-balance")
|
||||||
@account_required
|
@account_required
|
||||||
def faq():
|
def account_balance():
|
||||||
return render_template("billing.html")
|
errors = list()
|
||||||
|
payments = get_payments()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
return render_template("account-balance.html")
|
@ -108,7 +108,7 @@ def init_app(app):
|
|||||||
|
|
||||||
|
|
||||||
def get_model():
|
def get_model():
|
||||||
if 'model' not in g:
|
if 'db_model' not in g:
|
||||||
connection = current_app.config['PSYCOPG2_CONNECTION_POOL'].getconn()
|
connection = current_app.config['PSYCOPG2_CONNECTION_POOL'].getconn()
|
||||||
cursor = connection.cursor()
|
cursor = connection.cursor()
|
||||||
g.db_model = DBModel(connection, cursor)
|
g.db_model = DBModel(connection, cursor)
|
||||||
@ -116,11 +116,11 @@ def get_model():
|
|||||||
|
|
||||||
|
|
||||||
def close_db(e=None):
|
def close_db(e=None):
|
||||||
model = g.pop("model", None)
|
db_model = g.pop("db_model", None)
|
||||||
|
|
||||||
if model is not None:
|
if db_model is not None:
|
||||||
model.cursor.close()
|
db_model.cursor.close()
|
||||||
current_app.config['PSYCOPG2_CONNECTION_POOL'].putconn(model.connection)
|
current_app.config['PSYCOPG2_CONNECTION_POOL'].putconn(db_model.connection)
|
||||||
|
|
||||||
def my_exec_info_message(exec_info):
|
def my_exec_info_message(exec_info):
|
||||||
return "{}: {}".format(".".join([exec_info[0].__module__, exec_info[0].__name__]), exec_info[1])
|
return "{}: {}".format(".".join([exec_info[0].__module__, exec_info[0].__name__]), exec_info[1])
|
@ -80,12 +80,13 @@ class DBModel:
|
|||||||
|
|
||||||
def list_vms_for_account(self, email):
|
def list_vms_for_account(self, email):
|
||||||
self.cursor.execute("""
|
self.cursor.execute("""
|
||||||
SELECT vms.id, vms.last_seen_ipv4, vms.last_seen_ipv6, vms.size, vms.os, vms.created, vms.deleted
|
SELECT vms.id, vms.last_seen_ipv4, vms.last_seen_ipv6, vms.size, vms.os, vms.created, vms.deleted, vm_sizes.dollars_per_month
|
||||||
FROM vms WHERE vms.email = %s""",
|
FROM vms JOIN vm_sizes on vms.size = vm_sizes.id
|
||||||
|
WHERE vms.email = %s""",
|
||||||
(email, )
|
(email, )
|
||||||
)
|
)
|
||||||
return list(map(
|
return list(map(
|
||||||
lambda x: dict(id=x[0], ipv4=x[1], ipv6=x[2], size=x[3], os=x[4], created=x[5], deleted=x[6]),
|
lambda x: dict(id=x[0], ipv4=x[1], ipv6=x[2], size=x[3], os=x[4], created=x[5], deleted=x[6], dollars_per_month=x[7]),
|
||||||
self.cursor.fetchall()
|
self.cursor.fetchall()
|
||||||
))
|
))
|
||||||
|
|
||||||
@ -138,3 +139,15 @@ class DBModel:
|
|||||||
vm["ssh_public_keys"] = list(map( lambda x: x[0], self.cursor.fetchall() ))
|
vm["ssh_public_keys"] = list(map( lambda x: x[0], self.cursor.fetchall() ))
|
||||||
|
|
||||||
return vm
|
return vm
|
||||||
|
|
||||||
|
def list_payments_for_account(self, email):
|
||||||
|
self.cursor.execute("""
|
||||||
|
SELECT payments.id, payments.dollars, payments.created
|
||||||
|
FROM payments WHERE payments.email = %s""",
|
||||||
|
(email, )
|
||||||
|
)
|
||||||
|
return list(map(
|
||||||
|
lambda x: dict(id=x[0], dollars=x[1], created=x[2]),
|
||||||
|
self.cursor.fetchall()
|
||||||
|
))
|
||||||
|
|
||||||
|
@ -103,8 +103,8 @@ input, textarea, select, label {
|
|||||||
input, select, textarea {
|
input, select, textarea {
|
||||||
outline: 0;
|
outline: 0;
|
||||||
padding: 0.25em 0.5em;
|
padding: 0.25em 0.5em;
|
||||||
border-radius: 0.5em;
|
|
||||||
color: #bdc7b8;
|
color: #bdc7b8;
|
||||||
|
background-color: #bdc7b805;
|
||||||
}
|
}
|
||||||
|
|
||||||
select {
|
select {
|
||||||
@ -122,14 +122,9 @@ select {
|
|||||||
padding-right: 2em;
|
padding-right: 2em;
|
||||||
}
|
}
|
||||||
|
|
||||||
input, textarea {
|
input[type=text], textarea {
|
||||||
background: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
input[type=text] {
|
|
||||||
font: calc(0.40rem + 1vmin) monospace;
|
font: calc(0.40rem + 1vmin) monospace;
|
||||||
border: 0;
|
border: 1px solid #777e73;
|
||||||
border-bottom: 1px solid #777e73;
|
|
||||||
outline: 0;
|
outline: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -147,10 +142,10 @@ input[type=checkbox] {
|
|||||||
margin: 0;
|
margin: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
input[type=submit], select, textarea {
|
input[type=submit], select {
|
||||||
font: calc(0.40rem + 1vmin) monospace;
|
font: calc(0.40rem + 1vmin) monospace;
|
||||||
border: 1px solid #777e73;
|
border: 1px solid #777e73;
|
||||||
background-color: #bdc7b810;
|
border-radius: 0.5em;
|
||||||
}
|
}
|
||||||
|
|
||||||
input[type=submit], select {
|
input[type=submit], select {
|
||||||
|
14
capsulflask/templates/account-balance.html
Normal file
14
capsulflask/templates/account-balance.html
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
{% extends 'base.html' %}
|
||||||
|
|
||||||
|
{% block title %}Account Balance{% endblock %}
|
||||||
|
|
||||||
|
{% block content %}
|
||||||
|
<div class="third-margin">
|
||||||
|
<h1>Account Balance</h1>
|
||||||
|
</div>
|
||||||
|
<div class="half-margin">
|
||||||
|
|
||||||
|
</div>
|
||||||
|
{% endblock %}
|
||||||
|
|
||||||
|
{% block pagesource %}/templates/create-capsul.html{% endblock %}
|
@ -28,7 +28,7 @@
|
|||||||
{% if session["account"] %}
|
{% if session["account"] %}
|
||||||
<a href="/console">Capsuls</a>
|
<a href="/console">Capsuls</a>
|
||||||
<a href="/console/ssh">SSH Public Keys</a>
|
<a href="/console/ssh">SSH Public Keys</a>
|
||||||
<a href="/console/billing">Account Balance</a>
|
<a href="/console/account-balance">Account Balance</a>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
<a href="/support">Support</a>
|
<a href="/support">Support</a>
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{% extends 'base.html' %}
|
{% extends 'base.html' %}
|
||||||
|
|
||||||
{% block title %}Create{% endblock %}
|
{% block title %}{{ vm['id'] }}{% endblock %}
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
<div class="third-margin">
|
<div class="third-margin">
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{% extends 'base.html' %}
|
{% extends 'base.html' %}
|
||||||
|
|
||||||
{% block title %}Console{% endblock %}
|
{% block title %}Capsuls{% endblock %}
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
<div class="third-margin">
|
<div class="third-margin">
|
||||||
|
@ -69,7 +69,7 @@ f1-xxx $57.58 8 16G 25G 16TB
|
|||||||
</form>
|
</form>
|
||||||
{% else %}
|
{% else %}
|
||||||
<p>You don't have any ssh public keys yet.</p>
|
<p>You don't have any ssh public keys yet.</p>
|
||||||
<p>You must <a href="/console/ssh/upload">upload one</a> before you can create a Capsul.</p>
|
<p>You must <a href="/console/ssh">upload one</a> before you can create a Capsul.</p>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
Loading…
Reference in New Issue
Block a user