add hub-and-spoke diagrams to readme

This commit is contained in:
forest 2021-01-02 19:07:43 -06:00
parent b991ec89d2
commit 0a379b74ad
7 changed files with 47 additions and 20 deletions

View File

@ -121,6 +121,35 @@ In general, for safety, schema version upgrades should not delete data. Schema v
-----
## hub-and-spoke architecture
![](readme/hub-and-spoke1.png)
This diagram was created with https://app.diagrams.net/.
To edit it, download the <a download href="readme/hub-and-spoke.xml">diagram file</a> and edit it with the https://app.diagrams.net/ web application, or you may run the application from [source](https://github.com/jgraph/drawio) if you wish.
right now I have 2 types of operations, immediate mode and async.
both types of operations do assignment synchronously. so if the system cant assign the operation to one or more hosts (spokes),
or whatever the operation requires, then it will fail.
some operations tolerate partial failures, like, capacity_avaliable will succeed if at least one spoke succeeds
for immediate mode, assignment and completion of the operation (like `list`, `capacity_avaliable`, `destroy`) are the same thing
for async ones, they can be assigned without knowing whether or not they succeeded (`create`)
![](readme/hub-and-spoke2.png)
This diagram was created with https://app.diagrams.net/.
To edit it, download the <a download href="readme/hub-and-spoke.xml">diagram file</a> and edit it with the https://app.diagrams.net/ web application, or you may run the application from [source](https://github.com/jgraph/drawio) if you wish.
if you issue a create, and it technically could go to any number of hosts, but only one host responds, it will succeed
but if you issue a create and somehow 2 hosts both think they own that task, it will fail and throw a big error. cuz it expects exactly 1 to own the create task
currently its not set up to do any polling. its not really like a queue at all. It's all immediate for the most part
-----
## how to setup btcpay server
Generate a private key and the accompanying bitpay SIN for the btcpay API client.

View File

@ -6,7 +6,7 @@ from werkzeug.exceptions import abort
from capsulflask.db import get_model, my_exec_info_message
bp = Blueprint("hosts", __name__, url_prefix="/hosts")
bp = Blueprint("hub", __name__, url_prefix="/hub")
def authorized_for_host(id):
auth_header_value = request.headers.get('Authorization').replace("Bearer ", "")
@ -17,6 +17,6 @@ def heartbeat(id):
if authorized_for_host(id):
get_model().host_heartbeat(id)
else:
current_app.logger.info(f"/hosts/heartbeat/{id} returned 401: invalid token")
current_app.logger.info(f"/hub/heartbeat/{id} returned 401: invalid token")
return abort(401, "invalid host id or token")

View File

@ -1,4 +1,5 @@
import aiohttp
from flask import Blueprint
from flask import current_app
from flask import request
@ -6,17 +7,19 @@ from werkzeug.exceptions import abort
from capsulflask.db import get_model, my_exec_info_message
bp = Blueprint("hosts", __name__, url_prefix="/hosts")
bp = Blueprint("spoke", __name__, url_prefix="/spoke")
def authorized_for_host(id):
def authorized_as_hub(id):
auth_header_value = request.headers.get('Authorization').replace("Bearer ", "")
return get_model().authorized_for_host(id, auth_header_value)
return auth_header_value == current_app.config["HUB_TOKEN"]
@bp.route("/heartbeat/<string:id>", methods=("POST"))
def heartbeat(id):
if authorized_for_host(id):
get_model().host_heartbeat(id)
@bp.route("/heartbeat", methods=("POST"))
def heartbeat():
if authorized_as_hub(id):
# make request to hub-domain.com/hub/heartbeat/{current_app.config["SPOKE_HOST_ID"]}
# succeed or fail based on whether the request succeeds or fails.
pass
else:
current_app.logger.info(f"/hosts/heartbeat/{id} returned 401: invalid token")
return abort(401, "invalid host id or token")
current_app.logger.info(f"/hosts/heartbeat returned 401: invalid token")
return abort(401, "invalid hub token")

View File

@ -54,7 +54,6 @@ class MockSpoke(SpokeInterface):
def destroy(self, email: str, id: str):
current_app.logger.info(f"mock destroy: {id} for {email}")
class ShellScriptSpoke(SpokeInterface):
def validate_completed_process(self, completedProcess, email=None):
@ -157,17 +156,12 @@ class ShellScriptSpoke(SpokeInterface):
{completedProcess.stderr}
""")
def destroy(self, email: str, id: str):
def destroy(self, email: str, id: str) -> str:
validate_capsul_id(id)
completedProcess = run([join(current_app.root_path, 'shell_scripts/destroy.sh'), id], capture_output=True)
self.validate_completed_process(completedProcess, email)
lines = completedProcess.stdout.splitlines()
status = lines[len(lines)-1].decode("utf-8")
return status
if not status == "success":
raise ValueError(f"""failed to destroy vm "{id}" for {email}:
stdout:
{completedProcess.stdout}
stderr:
{completedProcess.stderr}
""")

1
readme/hub-and-spoke.xml Normal file
View File

@ -0,0 +1 @@
<mxfile host="app.diagrams.net" modified="2021-01-03T00:49:24.202Z" agent="5.0 (X11)" etag="bNLCzv8xp0QHJ2iOv8s8" version="14.1.8" type="device"><diagram id="2J8LUWl6CGm-7iVjfT5N" name="Page-1">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</diagram></mxfile>

BIN
readme/hub-and-spoke1.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 41 KiB

BIN
readme/hub-and-spoke2.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 58 KiB