1
Fork 0
mirror of https://github.com/Steffo99/sophon.git synced 2024-12-22 06:44:21 +00:00

💥 Things

This commit is contained in:
Steffo 2021-10-19 22:18:01 +02:00
parent 0555c9a97e
commit d85f57e04a
10 changed files with 57 additions and 34 deletions

View file

@ -39,7 +39,6 @@ class NotebookAdmin(SophonAdmin):
"fields": ( "fields": (
"container_image", "container_image",
"container_id", "container_id",
"internet_access",
), ),
}, },
), ),

View file

@ -0,0 +1,19 @@
# Generated by Django 3.2.7 on 2021-10-19 19:46
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('notebooks', '0011_auto_20211019_1745'),
]
operations = [
migrations.AlterField(
model_name='notebook',
name='internal_url',
field=models.CharField(blank=True,
help_text='The URL reachable from the proxy where the container is available. Can be null if the notebook is not running.',
max_length=512, null=True, verbose_name='Internal URL'),
),
]

View file

@ -114,10 +114,11 @@ class Notebook(SophonGroupModel):
blank=True, null=True, blank=True, null=True,
) )
internal_url = models.IntegerField( internal_url = models.CharField(
"Internal URL", "Internal URL",
help_text="The URL reachable from the proxy where the container is available. Can be null if the notebook is not running.", help_text="The URL reachable from the proxy where the container is available. Can be null if the notebook is not running.",
blank=True, null=True, blank=True, null=True,
max_length=512,
) )
def get_group(self) -> ResearchGroup: def get_group(self) -> ResearchGroup:
@ -131,7 +132,6 @@ class Notebook(SophonGroupModel):
"name", "name",
"locked_by", "locked_by",
"container_image", "container_image",
"internet_access",
"is_running", "is_running",
"lab_url", "lab_url",
"legacy_notebook_url", "legacy_notebook_url",
@ -174,28 +174,28 @@ class Notebook(SophonGroupModel):
""" """
:return: The name given to the container associated with this :class:`Notebook`. :return: The name given to the container associated with this :class:`Notebook`.
""" """
return f"{settings.CONTAINER_PREFIX}-{self.slug}" return f"{settings.DOCKER_CONTAINER_PREFIX}-{self.slug}"
@property @property
def volume_name(self) -> str: def volume_name(self) -> str:
""" """
:return: The name given to the volume associated with this :class:`Notebook`. :return: The name given to the volume associated with this :class:`Notebook`.
""" """
return f"{settings.VOLUME_PREFIX}-{self.slug}" return f"{settings.DOCKER_VOLUME_PREFIX}-{self.slug}"
@property @property
def network_name(self) -> str: def network_name(self) -> str:
""" """
:return: The name given to the network associated with this :class:`Notebook`. :return: The name given to the network associated with this :class:`Notebook`.
""" """
return f"{settings.NETWORK_PREFIX}-{self.slug}" return f"{settings.DOCKER_NETWORK_PREFIX}-{self.slug}"
@property @property
def external_domain(self) -> str: def external_domain(self) -> str:
""" """
:return: The domain name where this :class:`Notebook` will be accessible on the Internet after its container is started. :return: The domain name where this :class:`Notebook` will be accessible on the Internet after its container is started.
""" """
return f"{self.slug}.{settings.PROXY_DOMAIN}" return f"{self.slug}.{settings.PROXY_BASE_DOMAIN}"
@property @property
def lab_url(self) -> t.Optional[str]: def lab_url(self) -> t.Optional[str]:
@ -322,7 +322,10 @@ class Notebook(SophonGroupModel):
proxy = get_proxy_container() proxy = get_proxy_container()
self.log.debug("Disconnecting proxy container from the network...") self.log.debug("Disconnecting proxy container from the network...")
try:
network.disconnect(proxy) network.disconnect(proxy)
except docker.errors.APIError:
self.log.debug("Container was already disconnected.")
else: else:
self.log.debug("Unassigning port...") self.log.debug("Unassigning port...")
@ -485,7 +488,7 @@ class Notebook(SophonGroupModel):
name=self.container_name, name=self.container_name,
ports={ ports={
"8888/tcp": (f"127.0.0.1", f"{self.port}/tcp") "8888/tcp": (f"127.0.0.1", f"{self.port}/tcp")
}, } if self.port else {},
environment={ environment={
"JUPYTER_ENABLE_LAB": "yes", "JUPYTER_ENABLE_LAB": "yes",
"RESTARTABLE": "yes", "RESTARTABLE": "yes",
@ -498,7 +501,7 @@ class Notebook(SophonGroupModel):
"mode": "rw", "mode": "rw",
} }
}, },
network=network, network=network.name,
) )
self.log.debug("Storing container_id in the SQL database...") self.log.debug("Storing container_id in the SQL database...")

View file

@ -3,7 +3,8 @@ version: "3.9"
volumes: volumes:
proxy-data: proxy-data:
static-data: django-static:
react-static:
db-data: db-data:
@ -43,9 +44,9 @@ services:
# TODO: Configure your proxy details! # TODO: Configure your proxy details!
- DJANGO_PROXY_BASE_DOMAIN=dev.sophon.steffo.eu - DJANGO_PROXY_BASE_DOMAIN=dev.sophon.steffo.eu
- DJANGO_PROXY_PROTOCOL=http - DJANGO_PROXY_PROTOCOL=http
- DJANGO_PROXY_CONTAINER_NAME=proxy - DJANGO_PROXY_CONTAINER_NAME=sophon2-proxy-1 # The correct name probably is $DIRECTORYNAME-proxy-1
# TODO: Configure your static url! # TODO: Configure your static url!
- DJANGO_STATIC_URL=http://static.dev.sophon.steffo.eu/@django-static/ - DJANGO_STATIC_URL=http://static.dev.sophon.steffo.eu/django-static/
# TODO: Set your language! # TODO: Set your language!
- DJANGO_LANGUAGE_CODE=en-us - DJANGO_LANGUAGE_CODE=en-us
# TODO: Set your timezone! # TODO: Set your timezone!
@ -69,7 +70,7 @@ services:
- DJANGO_DOCKER_CERT_PATH= - DJANGO_DOCKER_CERT_PATH=
volumes: volumes:
- proxy-data:/run/sophon/proxy - proxy-data:/run/sophon/proxy
- static-data:/run/sophon/static - django-static:/run/sophon/static
- /var/run/docker.sock:/var/run/docker.sock - /var/run/docker.sock:/var/run/docker.sock
depends_on: depends_on:
- db - db
@ -88,7 +89,8 @@ services:
- SOPHON_FRONTEND_NAME=frontend:5000 - SOPHON_FRONTEND_NAME=frontend:5000
volumes: volumes:
- proxy-data:/run/sophon/proxy - proxy-data:/run/sophon/proxy
- static-data:/usr/local/apache2/htdocs/django-static - django-static:/usr/local/apache2/htdocs/django-static
- react-static:/usr/local/apache2/htdocs/react-static
depends_on: depends_on:
- backend - backend
- frontend - frontend

View file

@ -15,4 +15,5 @@ RUN yarn install
COPY . . COPY . .
# Start the serve server # Start the serve server
ENTRYPOINT ["yarn", "run", "serve"] ENTRYPOINT ["yarn", "run"]
CMD ["serve"]

View file

@ -5,6 +5,7 @@
<content url="file://$MODULE_DIR$"> <content url="file://$MODULE_DIR$">
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" /> <sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
<excludeFolder url="file://$MODULE_DIR$/src/components/legacy" /> <excludeFolder url="file://$MODULE_DIR$/src/components/legacy" />
<excludeFolder url="file://$MODULE_DIR$/build" />
</content> </content>
<orderEntry type="jdk" jdkName="Poetry (frontend)" jdkType="Python SDK" /> <orderEntry type="jdk" jdkName="Poetry (frontend)" jdkType="Python SDK" />
<orderEntry type="sourceFolder" forTests="false" /> <orderEntry type="sourceFolder" forTests="false" />

View file

@ -3,12 +3,13 @@ import {FontAwesomeIcon} from "@fortawesome/react-fontawesome"
import {Box, Heading, Idiomatic} from "@steffo/bluelib-react" import {Box, Heading, Idiomatic} from "@steffo/bluelib-react"
import * as React from "react" import * as React from "react"
import ReactMarkdown from "react-markdown" import ReactMarkdown from "react-markdown"
import {Empty} from "./Empty"
export interface DescriptionBoxProps { export interface DescriptionBoxProps {
icon: IconDefinition, icon: IconDefinition,
name: string, name: string,
description: string, description?: string | null,
} }
@ -19,9 +20,16 @@ export function DescriptionBox({icon, name, description}: DescriptionBoxProps):
<Heading level={3}> <Heading level={3}>
<FontAwesomeIcon icon={icon}/>&nbsp;About <Idiomatic>{name}</Idiomatic> <FontAwesomeIcon icon={icon}/>&nbsp;About <Idiomatic>{name}</Idiomatic>
</Heading> </Heading>
{
description ?
<ReactMarkdown> <ReactMarkdown>
{description} {description}
</ReactMarkdown> </ReactMarkdown>
:
<Empty>
This resource has no about text.
</Empty>
}
</Box> </Box>
), ),
[icon, name, description], [icon, name, description],

View file

@ -16,10 +16,6 @@ export function InstanceDescriptionBox(): JSX.Element | null {
return null return null
} }
if(!instance.state.details.description) {
return null
}
return ( return (
<DescriptionBox <DescriptionBox
icon={faUniversity} icon={faUniversity}

View file

@ -1,4 +1,4 @@
import {DjangoResource, DjangoSlug} from "./DjangoTypes"; import {DjangoResource, DjangoSlug} from "./DjangoTypes"
/** /**
@ -64,9 +64,8 @@ export interface SophonNotebook extends DjangoResource {
locked_by: number, locked_by: number,
slug: DjangoSlug, slug: DjangoSlug,
legacy_notebook_url: string | null, legacy_notebook_url: string | null,
jupyter_token: string, jupyter_token?: string,
is_running: boolean, is_running: boolean,
internet_access: true,
container_image: string, container_image: string,
project: DjangoSlug, project: DjangoSlug,
name: string, name: string,

View file

@ -561,12 +561,13 @@ RewriteEngine on
# Preserve host # Preserve host
ProxyPreserveHost on ProxyPreserveHost on
# Proxy regular requests to the frontend # Proxy regular requests to the frontend
# sophon.steffo.eu → frontend # sophon.steffo.eu → frontend
RewriteCond "%{ENV:matched}" "! -eq 1" [NC] # If the url hasn't been matched by the previous rules RewriteCond "%{ENV:matched}" "! -eq 1" [NC] # If the url hasn't been matched by the previous rules
RewriteCond "%{ENV:APACHE_PROXY_BASE_DOMAIN} %{HTTP_HOST}" "^([^ ]+) \1$" [NC] # If ENV:APACHE_PROXY_BASE_DOMAIN equals HTTP_HOST RewriteCond "%{ENV:APACHE_PROXY_BASE_DOMAIN} %{HTTP_HOST}" "^([^ ]+) \1$" [NC] # If ENV:APACHE_PROXY_BASE_DOMAIN equals HTTP_HOST
RewriteCond "%{ENV:SOPHON_FRONTEND_NAME}" "^(.+)$" [NC] # Capture ENV:SOPHON_FRONTEND_NAME for substitution in the rewriterule RewriteCond "%{ENV:SOPHON_FRONTEND_NAME}" "^(.+)$" [NC] # Capture ENV:SOPHON_FRONTEND_NAME for substitution in the rewriterule
RewriteRule "/(.*)" "http://%1/$1" [P,L,E=matched:1] # Rewrite and set the matched flag RewriteRule "/(.*)" "http://%1/$1" [P,L,E=matched:1] # Rewrite as a SPA and set the matched flag
# Proxy api requests to the backend # Proxy api requests to the backend
# api.sophon.steffo.eu → backend # api.sophon.steffo.eu → backend
@ -575,12 +576,6 @@ RewriteCond "api.%{ENV:APACHE_PROXY_BASE_DOMAIN} %{HTTP_HOST}" "^([^ ]+) \1$" [N
RewriteCond "%{ENV:SOPHON_BACKEND_NAME}" "^(.+)$" [NC] # Capture ENV:SOPHON_BACKEND_NAME for substitution in the rewriterule RewriteCond "%{ENV:SOPHON_BACKEND_NAME}" "^(.+)$" [NC] # Capture ENV:SOPHON_BACKEND_NAME for substitution in the rewriterule
RewriteRule "/(.*)" "http://%1/$1" [P,L,E=matched:1] # Rewrite and set the matched flag RewriteRule "/(.*)" "http://%1/$1" [P,L,E=matched:1] # Rewrite and set the matched flag
# Proxy static requests to the static files
# static.sophon.steffo.eu → static
RewriteCond "%{ENV:matched}" "! -eq 1" [NC] # If the url hasn't been matched by the previous rules
RewriteCond "static.%{ENV:APACHE_PROXY_BASE_DOMAIN} %{HTTP_HOST}" "^([^ ]+) \1$" [NC] # If static. prefixed to ENV:APACHE_PROXY_BASE_DOMAIN equals HTTP_HOST
RewriteRule "/@django-static/(.*)" "/django-static/$1" [P,L,E=matched:1] # Rewrite and set the matched flag
# Create a map between the proxy file generated by Sophon and Apache # Create a map between the proxy file generated by Sophon and Apache
RewriteMap "sophonproxy" "dbm=gdbm:/run/sophon/proxy/proxy.dbm" RewriteMap "sophonproxy" "dbm=gdbm:/run/sophon/proxy/proxy.dbm"