Merge branch 'mysql'

This commit is contained in:
dave 2019-04-15 21:37:58 -07:00
commit a8787d0ff2
7 changed files with 56 additions and 21 deletions

View File

@ -20,7 +20,7 @@ ADD . /tmp/code/
COPY --from=0 /tmp/code/styles/dist/style.css /tmp/code/styles/dist/style.css COPY --from=0 /tmp/code/styles/dist/style.css /tmp/code/styles/dist/style.css
RUN apt-get update && \ RUN apt-get update && \
apt-get install -y python3-pip sudo apt-get install -y python3-pip sudo git
RUN pip3 install -U pip && \ RUN pip3 install -U pip && \
cd /tmp/code && \ cd /tmp/code && \
@ -28,8 +28,6 @@ RUN pip3 install -U pip && \
python3 setup.py install && \ python3 setup.py install && \
useradd --uid 1000 app useradd --uid 1000 app
VOLUME /data/
ADD start /start ADD start /start
ENTRYPOINT ["/start"] ENTRYPOINT ["/start"]

View File

@ -8,6 +8,9 @@ import tempfile
import subprocess import subprocess
import sys
APPNAME = "npcli" APPNAME = "npcli"
CONFDIR = user_config_dir(APPNAME) CONFDIR = user_config_dir(APPNAME)
CONFPATH = os.path.join(CONFDIR, "conf.json") CONFPATH = os.path.join(CONFDIR, "conf.json")
@ -74,6 +77,9 @@ def main():
spr_dump = spr_action.add_parser("dump", help="dump the database") spr_dump = spr_action.add_parser("dump", help="dump the database")
spr_import = spr_action.add_parser("import", help="import a database dump")
spr_import.add_argument("fname", help="db dump yaml file to import")
args = parser.parse_args() args = parser.parse_args()
r = requests.session() r = requests.session()
@ -131,6 +137,21 @@ def main():
print(yaml.dump(dump, default_flow_style=False)) print(yaml.dump(dump, default_flow_style=False))
elif args.action == "import":
with open(args.fname) as f:
dump = yaml.load(f)
for clsname in dump["classes"]:
r.put(args.host.rstrip("/") + "/api/class/" + clsname).raise_for_status()
# just make the nodes first
for nodename, nodebody in dump["nodes"].items():
putnode(nodename, yaml.dump({"body": {}, "classes": {}, "parents": []})).raise_for_status()
# then fill out node bodies to avoid missing parent ordering issues
for nodename, nodebody in dump["nodes"].items():
putnode(nodename, yaml.dump(nodebody)).raise_for_status()
if __name__ == "__main__": if __name__ == "__main__":
main() main()

View File

@ -3,10 +3,10 @@ import cherrypy
import logging import logging
from nodepupper.nodeops import NodeOps, NObject, NClass, NClassAttachment from nodepupper.nodeops import NodeOps, NObject, NClass, NClassAttachment
from jinja2 import Environment, FileSystemLoader, select_autoescape from jinja2 import Environment, FileSystemLoader, select_autoescape
from nodepupper.common import pwhash
import math
from urllib.parse import urlparse from urllib.parse import urlparse
import math
import yaml import yaml
import sys
APPROOT = os.path.abspath(os.path.join(os.path.dirname(__file__), "../")) APPROOT = os.path.abspath(os.path.join(os.path.dirname(__file__), "../"))
@ -206,7 +206,8 @@ class ClassesApi(object):
def PUT(self, cls): def PUT(self, cls):
with self.nodes.db.transaction() as c: with self.nodes.db.transaction() as c:
c.root.classes[cls] = NClass(cls) if cls not in c.root.classes:
c.root.classes[cls] = NClass(cls)
def DELETE(self, cls): def DELETE(self, cls):
with self.nodes.db.transaction() as c: with self.nodes.db.transaction() as c:
@ -278,7 +279,8 @@ def main():
parser.add_argument('-p', '--port', default=8080, type=int, help="tcp port to listen on") parser.add_argument('-p', '--port', default=8080, type=int, help="tcp port to listen on")
# parser.add_argument('-l', '--library', default="./library", help="library path") # parser.add_argument('-l', '--library', default="./library", help="library path")
# parser.add_argument('-c', '--cache', default="./cache", help="cache path") # parser.add_argument('-c', '--cache', default="./cache", help="cache path")
parser.add_argument('-s', '--database', default="./pupper.db", help="path to persistent sqlite database") parser.add_argument('-s', '--database', default=os.environ.get('DATABASE_URI', None),
help="mysql:// connection uri")
parser.add_argument('--debug', action="store_true", help="enable development options") parser.add_argument('--debug', action="store_true", help="enable development options")
args = parser.parse_args() args = parser.parse_args()
@ -286,6 +288,10 @@ def main():
logging.basicConfig(level=logging.INFO if args.debug else logging.WARNING, logging.basicConfig(level=logging.INFO if args.debug else logging.WARNING,
format="%(asctime)-15s %(levelname)-8s %(filename)s:%(lineno)d %(message)s") format="%(asctime)-15s %(levelname)-8s %(filename)s:%(lineno)d %(message)s")
if not args.database:
print("--database or $DATABASE_URI is required")
sys.exit(2)
library = NodeOps(args.database) library = NodeOps(args.database)
tpl_dir = os.path.join(APPROOT, "templates") if not args.debug else "templates" tpl_dir = os.path.join(APPROOT, "templates") if not args.debug else "templates"

View File

@ -1,5 +1,8 @@
from urllib.parse import urlparse
import ZODB import ZODB
import ZODB.FileStorage from relstorage.storage import RelStorage
from relstorage.options import Options
from relstorage.adapters.mysql import MySQLAdapter
import persistent import persistent
import persistent.list import persistent.list
import persistent.mapping import persistent.mapping
@ -40,8 +43,12 @@ class NClassAttachment(persistent.Persistent):
class NodeOps(object): class NodeOps(object):
def __init__(self, db_path): def __init__(self, db_uri):
self.storage = ZODB.FileStorage.FileStorage(db_path) uri = urlparse(db_uri)
self.mysql = MySQLAdapter(host=uri.hostname, user=uri.username, passwd=uri.password, db=uri.path[1:],
options=Options(keep_history=False))
self.storage = RelStorage(adapter=self.mysql)
self.db = ZODB.DB(self.storage) self.db = ZODB.DB(self.storage)
with self.db.transaction() as c: with self.db.transaction() as c:

View File

@ -1,26 +1,35 @@
appdirs==1.4.3 appdirs==1.4.3
asn1crypto==0.24.0
backports.functools-lru-cache==1.5 backports.functools-lru-cache==1.5
BTrees==4.5.1 BTrees==4.5.1
certifi==2018.11.29 certifi==2018.11.29
cffi==1.12.2
chardet==3.0.4 chardet==3.0.4
cheroot==6.5.2 cheroot==6.5.2
CherryPy==18.0.1 CherryPy==18.0.1
cryptography==2.6.1
idna==2.8 idna==2.8
jaraco.functools==1.20 jaraco.functools==1.20
Jinja2==2.10 Jinja2==2.10
MarkupSafe==1.0 MarkupSafe==1.0
more-itertools==4.3.0 more-itertools==4.3.0
perfmetrics==2.0
persistent==4.4.2 persistent==4.4.2
portend==2.3 portend==2.3
pycparser==2.19
PyMySQL==0.9.3
pytz==2018.5 pytz==2018.5
PyYAML==3.13 PyYAML==3.13
-e git+https://git.davepedu.com/dave/relstorage.git@5ae138b71a0eeb740208e61cfd1662c49738ee45#egg=RelStorage
requests==2.21.0 requests==2.21.0
six==1.11.0 six==1.11.0
tempora==1.13 tempora==1.13
transaction==2.2.1 transaction==2.4.0
urllib3==1.24.1 urllib3==1.24.1
zc.lockfile==1.3.0 zc.lockfile==1.3.0
ZConfig==3.3.0 ZConfig==3.3.0
ZODB==5.4.0 zdaemon==4.3
ZEO==5.2.1
ZODB==5.5.1
zodbpickle==1.0.2 zodbpickle==1.0.2
zope.interface==4.5.0 zope.interface==4.5.0

View File

@ -4,9 +4,9 @@ from setuptools import setup
import os import os
__version__ = "0.0.1" __version__ = "0.0.2"
with open(os.path.join(os.path.dirname(__file__), "requirements.txt")) as f: with open(os.path.join(os.path.dirname(__file__), "requirements.txt")) as f:
__requirements__ = [line.strip() for line in f.readlines()] __requirements__ = [line.strip() for line in f.readlines() if not line.startswith("-")]
setup(name='nodepupper', setup(name='nodepupper',

8
start
View File

@ -1,9 +1,3 @@
#!/bin/sh #!/bin/sh
exec sudo --preserve-env -Hu app nodepupperd $@
mkdir /data/db
chown -R app:app /data/db
exec sudo -Hu app nodepupperd --database /data/db/pup.db $@