Skip to content

Commit

Permalink
Merge pull request #316 from SelfhostedPro/develop
Browse files Browse the repository at this point in the history
Alpha v0.0.6-hf1
  • Loading branch information
SelfhostedPro authored Feb 24, 2021
2 parents 930b8b1 + 5f4fdaa commit 127cabd
Show file tree
Hide file tree
Showing 42 changed files with 22,368 additions and 997 deletions.
5 changes: 3 additions & 2 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -29,12 +29,13 @@ RUN \
make \
python3-dev \
libffi-dev \
ruby-dev \
postgresql-dev &&\
ruby-dev &&\
echo "**** install packages ****" && \
apk add --no-cache \
python3 \
py3-pip \
postgresql-dev \
mysql-dev \
nginx &&\
gem install sass &&\
echo "**** Installing Python Modules ****" && \
Expand Down
3 changes: 0 additions & 3 deletions backend/api/actions/__init__.py
Original file line number Diff line number Diff line change
@@ -1,3 +0,0 @@
from .apps import *
from .compose import *
from .resources import *
49 changes: 28 additions & 21 deletions backend/api/actions/apps.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,21 @@
from sqlalchemy.orm import Session
from sqlalchemy.exc import IntegrityError
from fastapi import HTTPException, BackgroundTasks
from ..db import models, schemas
from ..utils import *
from ..utils import check_updates as _update_check
from docker.errors import APIError

from datetime import datetime
from fastapi import HTTPException

from api.db.schemas.apps import DeployLogs, DeployForm, AppLogs, Processes
from api.utils.apps import (
conv_caps2data,
conv_devices2data,
conv_env2data,
conv_image2data,
conv_labels2data,
conv_portlabels2data,
conv_ports2data,
conv_restart2data,
conv_sysctls2data,
conv_volumes2data,
_check_updates,
)
from api.utils.templates import conv2dict

import time
import subprocess
import docker
Expand Down Expand Up @@ -48,7 +57,7 @@ def check_app_update(app_name):
)

if app.attrs["Config"]["Image"]:
if _update_check(app.attrs["Config"]["Image"]):
if _check_updates(app.attrs["Config"]["Image"]):
app.attrs.update(conv2dict("isUpdatable", True))
app.attrs.update(conv2dict("name", app.name))
app.attrs.update(conv2dict("ports", app.ports))
Expand Down Expand Up @@ -119,9 +128,7 @@ def get_app_processes(app_name):
app = dclient.containers.get(app_name)
if app.status == "running":
processes = app.top()
return schemas.Processes(
Processes=processes["Processes"], Titles=processes["Titles"]
)
return Processes(Processes=processes["Processes"], Titles=processes["Titles"])
else:
return None

Expand All @@ -136,7 +143,7 @@ def get_app_logs(app_name):
dclient = docker.from_env()
app = dclient.containers.get(app_name)
if app.status == "running":
return schemas.AppLogs(logs=app.logs())
return AppLogs(logs=app.logs())
else:
return None

Expand All @@ -147,7 +154,7 @@ def get_app_logs(app_name):
"""


def deploy_app(template: schemas.DeployForm):
def deploy_app(template: DeployForm):
try:
launch = launch_app(
template.name,
Expand All @@ -164,7 +171,7 @@ def deploy_app(template: schemas.DeployForm):
conv_sysctls2data(template.sysctls),
conv_caps2data(template.cap_add),
edit=template.edit or False,
id=template.id or None
_id=template.id or None,
)
except HTTPException as exc:
raise HTTPException(status_code=exc.status_code, detail=exc.detail)
Expand All @@ -174,7 +181,7 @@ def deploy_app(template: schemas.DeployForm):
)
print("done deploying")

return schemas.DeployLogs(logs=launch.logs())
return DeployLogs(logs=launch.logs())


"""
Expand Down Expand Up @@ -218,14 +225,14 @@ def launch_app(
sysctls,
caps,
edit,
id
_id,
):
dclient = docker.from_env()
if edit == True:
try:
dclient.containers.get(id)
dclient.containers.get(_id)
try:
running_app = dclient.containers.get(id)
running_app = dclient.containers.get(_id)
running_app.remove(force=True)
except Exception as e:
raise e
Expand Down Expand Up @@ -416,4 +423,4 @@ def check_self_update():
else:
raise HTTPException(status_code=400, detail=exc.args)

return _update_check(yacht.image.tags[0])
return _check_updates(yacht.image.tags[0])
64 changes: 62 additions & 2 deletions backend/api/actions/compose.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,16 @@
from fastapi import HTTPException
from fastapi.responses import StreamingResponse
from sh import docker_compose
import os
import yaml
import pathlib
import shutil
import docker
import io
import zipfile

from ..settings import Settings
from ..utils.compose import find_yml_files, get_readme_file, get_logo_file
from api.settings import Settings
from api.utils.compose import find_yml_files

settings = Settings()

Expand Down Expand Up @@ -297,3 +301,59 @@ def delete_compose(project_name):
except Exception as exc:
raise HTTPException(exc.status_code, exc.strerror)
return get_compose_projects()


def generate_support_bundle(project_name):
files = find_yml_files(settings.COMPOSE_DIR + project_name)
if project_name in files:
dclient = docker.from_env()
stream = io.BytesIO()
with zipfile.ZipFile(stream, "w") as zf, open(files[project_name], "r") as fp:
compose = yaml.load(fp, Loader=yaml.SafeLoader)
# print(compose)
# print(compose.get("services"))
for _service in compose.get("services"):
print()
if len(compose.get("services").keys()) < 2:
try:
if compose.get("services")[_service].get("container_name"):
service = dclient.containers.get(
compose.get("services")[_service].get("container_name")
)
else:
service = dclient.containers.get(_service)
except docker.errors.NotFound as exc:
raise HTTPException(
exc.status_code,
detail="container " + _service + " not found",
)
else:
try:
if compose.get("services")[_service].get("container_name"):
service = dclient.containers.get(
compose.get("services")[_service].get("container_name")
)
else:
service = dclient.containers.get(
project_name.lower() + "_" + _service + "_1"
)
except docker.errors.NotFound as exc:
raise HTTPException(
exc.status_code,
detail="container " + _service + " not found",
)
service_log = service.logs()
zf.writestr(f"{_service}.log", service_log)
fp.seek(0)
# It is possible that ".write(...)" has better memory management here.
zf.writestr("docker-compose.yml", fp.read())
stream.seek(0)
return StreamingResponse(
stream,
media_type="application/x-zip-compressed",
headers={
"Content-Disposition": f"attachment;filename={project_name}_bundle.zip"
},
)
else:
raise HTTPException(404, f"Project {project_name} not found.")
1 change: 0 additions & 1 deletion backend/api/actions/resources.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import docker
import json
from fastapi import HTTPException

### IMAGES ###
Expand Down
1 change: 0 additions & 1 deletion backend/api/auth/__init__.py
Original file line number Diff line number Diff line change
@@ -1 +0,0 @@
from .auth import *
5 changes: 2 additions & 3 deletions backend/api/auth/auth.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
from typing import Tuple

from ..settings import Settings
from api.settings import Settings

from fastapi import Depends, HTTPException
from fastapi_jwt_auth import AuthJWT
from fastapi import HTTPException
from fastapi_jwt_auth.exceptions import JWTDecodeError

from passlib import pwd
Expand Down
3 changes: 0 additions & 3 deletions backend/api/db/crud/__init__.py
Original file line number Diff line number Diff line change
@@ -1,3 +0,0 @@
from .templates import *
from .settings import *
from .users import *
7 changes: 1 addition & 6 deletions backend/api/db/crud/settings.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,7 @@
from sqlalchemy.orm import Session
from sqlalchemy.exc import IntegrityError
from sqlalchemy.orm.session import make_transient

from .. import models, schemas

from api.db.models import containers as models
from datetime import datetime
import urllib.request
import sqlite3
import json


Expand Down
16 changes: 7 additions & 9 deletions backend/api/db/crud/templates.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
from sqlalchemy.orm import Session
from sqlalchemy.exc import IntegrityError
from sqlalchemy.orm.session import make_transient

from fastapi import HTTPException

from .. import models, schemas
from ...utils import conv_ports2dict, conv_sysctls2dict
from api.db.models import containers as models
from api.utils.templates import conv_sysctls2dict, conv_ports2dict

from datetime import datetime
import urllib.request
Expand Down Expand Up @@ -46,12 +45,12 @@ def delete_template(db: Session, template_id: int):
return _template


def add_template(db: Session, template: models.containers.Template):
def add_template(db: Session, template: models.Template):
try:
_template_path = urlparse(template.url).path
ext = os.path.splitext(_template_path)[1]
# Opens the JSON and iterate over the content.
_template = models.containers.Template(title=template.title, url=template.url)
_template = models.Template(title=template.title, url=template.url)
with urllib.request.urlopen(template.url) as file:
if ext.rstrip() in (".yml", ".yaml"):
loaded_file = yaml.load(file, Loader=yaml.SafeLoader)
Expand All @@ -67,7 +66,7 @@ def add_template(db: Session, template: models.containers.Template):

# Optional use classmethod from_dict
try:
template_content = models.containers.TemplateItem(
template_content = models.TemplateItem(
type=int(entry.get("type", 1)),
title=entry["title"],
platform=entry["platform"],
Expand Down Expand Up @@ -100,7 +99,7 @@ def add_template(db: Session, template: models.containers.Template):
sysctls = conv_sysctls2dict(entry.get("sysctls", []))

# Optional use classmethod from_dict
template_content = models.containers.TemplateItem(
template_content = models.TemplateItem(
type=int(entry.get("type", 1)),
title=entry["title"],
platform=entry["platform"],
Expand Down Expand Up @@ -134,7 +133,6 @@ def add_template(db: Session, template: models.containers.Template):
# TODO raises IntegrityError on duplicates (uniqueness)
# status
db.rollback()
pass

return get_template(db=db, url=template.url)

Expand Down Expand Up @@ -192,7 +190,7 @@ def refresh_template(db: Session, template_id: id):
sysctls = conv_sysctls2dict(entry.get("sysctls", []))

# Optional use classmethod from_dict
template_content = models.containers.TemplateItem(
template_content = models.TemplateItem(
type=int(entry["type"]),
title=entry["title"],
platform=entry["platform"],
Expand Down
3 changes: 2 additions & 1 deletion backend/api/db/crud/users.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
from sqlalchemy.orm import Session
from passlib.context import CryptContext
from . import models, schemas
from api.db.models import users as models
from api.db.schemas import users as schemas
from fastapi.exceptions import HTTPException

pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto")
Expand Down
11 changes: 7 additions & 4 deletions backend/api/db/database.py
Original file line number Diff line number Diff line change
@@ -1,15 +1,18 @@
from sqlalchemy import create_engine
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker, session
from sqlalchemy.orm import sessionmaker
from ..settings import Settings

settings = Settings()

SQLALCHEMY_DATABASE_URL = settings.SQLALCHEMY_DATABASE_URI

engine = create_engine(
SQLALCHEMY_DATABASE_URL, connect_args={"check_same_thread": False}
)
if "sqlite:///" in SQLALCHEMY_DATABASE_URL:
engine = create_engine(
SQLALCHEMY_DATABASE_URL, connect_args={"check_same_thread": False}
)
else:
engine = create_engine(SQLALCHEMY_DATABASE_URL)
SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)

Base = declarative_base()
2 changes: 0 additions & 2 deletions backend/api/db/models/__init__.py
Original file line number Diff line number Diff line change
@@ -1,2 +0,0 @@
from .containers import *
from .users import *
3 changes: 1 addition & 2 deletions backend/api/db/models/containers.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
from sqlalchemy import (
Boolean,
Column,
ForeignKey,
Integer,
Expand All @@ -10,7 +9,7 @@
)
from sqlalchemy.orm import relationship

from ..database import Base
from api.db.database import Base

from datetime import datetime

Expand Down
8 changes: 5 additions & 3 deletions backend/api/db/models/users.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
from sqlalchemy import Boolean, Column, ForeignKey, Integer, String
from ..database import Base
from sqlalchemy import Boolean, Column, Integer, String
from api.db.database import Base


class User(Base):
__tablename__ = "user"

id = Column(Integer, primary_key=True, index=True)
username = Column("email", String, unique=True, index=True, nullable=False)
username = Column(
"email", String(length=264), unique=True, index=True, nullable=False
)
hashed_password = Column(String(length=72), nullable=False)
is_active = Column(Boolean, default=True, nullable=False)
is_superuser = Column(Boolean, default=False, nullable=False)
4 changes: 0 additions & 4 deletions backend/api/db/schemas/__init__.py
Original file line number Diff line number Diff line change
@@ -1,4 +0,0 @@
from .apps import *
from .templates import *
from .users import *
from .compose import *
2 changes: 1 addition & 1 deletion backend/api/db/schemas/apps.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ class DevicesSchema(BaseModel):


class LabelSchema(BaseModel):
name: str
label: str
value: str


Expand Down
1 change: 0 additions & 1 deletion backend/api/db/schemas/resources.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
from fastapi import FastAPI
from pydantic import BaseModel
from typing import Optional

Expand Down
Loading

0 comments on commit 127cabd

Please sign in to comment.