Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Port labels #109

Merged
merged 4 commits into from
Sep 24, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ Yacht is a container management UI with a focus on templates and 1-click deploym
## Installation:
Currently only linux has been verified as working but we are open to the idea of supporting windows eventually as well.

**Keep in mind, this is a pre-alpha so the risk of data loss is real and it may not be stable**
**Keep in mind, this is an alpha so the risk of data loss is real and it may not be stable**

Once docker is installed you'll simply run the following commands to get started:
```
Expand Down
6 changes: 5 additions & 1 deletion backend/api/actions/apps.py
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ def deploy_app(template: schemas.DeployForm):
template.image,
conv_restart2data(template.restart_policy),
conv_ports2data(template.ports),
conv_portlabels2data(template.ports),
conv_volumes2data(template.volumes),
conv_env2data(template.env),
conv_sysctls2data(template.sysctls),
Expand All @@ -85,8 +86,10 @@ def deploy_app(template: schemas.DeployForm):

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

def Merge(dict1, dict2):
return(dict2.update(dict1))

def launch_app(name, image, restart_policy, ports, volumes, env, sysctls, caps):
def launch_app(name, image, restart_policy, ports, portlabels, volumes, env, sysctls, caps):
dclient = docker.from_env()
lauch = dclient.containers.run(
name=name,
Expand All @@ -96,6 +99,7 @@ def launch_app(name, image, restart_policy, ports, volumes, env, sysctls, caps):
volumes=volumes,
environment=env,
sysctls=sysctls,
labels=portlabels,
cap_add=caps,
detach=True
)
Expand Down
63 changes: 57 additions & 6 deletions backend/api/db/crud/templates.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,8 +54,33 @@ def add_template(db: Session, template: models.containers.Template):
else:
print('Invalid filetype')
raise
for entry in loaded_file:

if type(loaded_file) == list:
for entry in loaded_file:
if entry.get('ports'):
ports = conv_ports2dict(entry.get('ports', []))
sysctls = conv_sysctls2dict(entry.get('sysctls', []))

# Optional use classmethod from_dict
template_content = models.containers.TemplateItem(
type=int(entry['type']),
title=entry['title'],
platform=entry['platform'],
description=entry.get('description', ''),
name=entry.get('name', entry['title'].lower()),
logo=entry.get('logo', ''), # default logo here!
image=entry.get('image', ''),
notes=entry.get('note', ''),
categories=entry.get('categories', ''),
restart_policy=entry.get('restart_policy'),
ports=ports,
volumes=entry.get('volumes', []),
env=entry.get('env', []),
sysctls=sysctls,
cap_add=entry.get('cap_add', [])
)
_template.items.append(template_content)
elif type(loaded_file) == dict:
entry = loaded_file
ports = conv_ports2dict(entry.get('ports', []))
sysctls = conv_sysctls2dict(entry.get('sysctls', []))

Expand Down Expand Up @@ -112,12 +137,38 @@ def refresh_template(db: Session, template_id: id):
else:
print('Invalid filetype')
raise
for entry in loaded_file:

if type(loaded_file) == list:
for entry in loaded_file:

if entry.get('ports'):
ports = conv_ports2dict(entry.get('ports', []))
sysctls = conv_sysctls2dict(entry.get('sysctls', []))

item = models.TemplateItem(
type=int(entry['type']),
title=entry['title'],
platform=entry['platform'],
description=entry.get('description', ''),
name=entry.get('name', entry['title'].lower()),
logo=entry.get('logo', ''), # default logo here!
image=entry.get('image', ''),
notes=entry.get('note', ''),
categories=entry.get('categories', ''),
restart_policy=entry.get('restart_policy'),
ports=ports,
volumes=entry.get('volumes', []),
env=entry.get('env', []),
sysctls=sysctls,
cap_add=entry.get('cap_add', [])
)
items.append(item)
elif type(loaded_file) == dict:
entry = loaded_file
ports = conv_ports2dict(entry.get('ports', []))
sysctls = conv_sysctls2dict(entry.get('sysctls', []))

item = models.TemplateItem(
# Optional use classmethod from_dict
template_content = models.containers.TemplateItem(
type=int(entry['type']),
title=entry['title'],
platform=entry['platform'],
Expand All @@ -134,7 +185,7 @@ def refresh_template(db: Session, template_id: id):
sysctls=sysctls,
cap_add=entry.get('cap_add', [])
)
items.append(item)
items.append(template_content)
except Exception as exc:
print('Template update failed. ERR_001', exc)
raise
Expand Down
1 change: 1 addition & 0 deletions backend/api/db/schemas/apps.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@


class PortsSchema(BaseModel):
label: Optional[str]
cport: str
hport: Optional[str]
proto: str
Expand Down
56 changes: 42 additions & 14 deletions backend/api/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,20 +43,38 @@ def get_db():


def conv_ports2dict(data: List[str]) -> List[Dict[str, str]]:
delim = ':'
portlst = []
for port_data in data:
if not re.match(REGEXP_PORT_ASSIGN, port_data, flags=re.IGNORECASE):
raise ValueError('Malformed port assignment.')

hport, cport = None, port_data
if delim in cport:
hport, cport = cport.split(delim, 1)
if not hport:
hport = None
cport, proto = cport.split('/', 1)
portlst.append({'cport': cport, 'hport': hport, 'proto': proto})
return portlst
if type(data[0]) == dict:
delim = ':'
portlst = []
for port_data in data:
for label, port in port_data.items():
if not re.match(REGEXP_PORT_ASSIGN, port, flags=re.IGNORECASE):
raise ValueError('Malformed port assignment.')

hport, cport = None, port
if delim in cport:
hport, cport = cport.split(delim, 1)
if not hport:
hport = None
cport, proto = cport.split('/', 1)
portlst.append({'cport': cport, 'hport': hport, 'proto': proto, 'label': label})
return portlst

elif type(data) == list:
delim = ':'
portlst = []
for port_data in data:
if not re.match(REGEXP_PORT_ASSIGN, port_data, flags=re.IGNORECASE):
raise ValueError('Malformed port assignment.')

hport, cport = None, port_data
if delim in cport:
hport, cport = cport.split(delim, 1)
if not hport:
hport = None
cport, proto = cport.split('/', 1)
portlst.append({'cport': cport, 'hport': hport, 'proto': proto})
return portlst

# Input Format:
# [
Expand Down Expand Up @@ -108,6 +126,16 @@ def conv_ports2data(data):
ports.update({str(cport)+'/'+proto: hport for d in data})
return ports

def conv_portlabels2data(data):
labels = {}
for d in data:
if d.label and d.hport:
labels.update({ 'local.yacht.port.'+d.hport: d.label })
print(data)
elif d.label:
print("in order to have a label the hostport must be set")
return None
return labels
# Input Format:
# [
# {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -83,13 +83,15 @@
<template v-slot:default>
<thead>
<tr>
<th class="text-center"> Label </th>
<th class="text-center">Container Port</th>
<th class="text-center">Host IP</th>
<th class="text-center">Host Port</th>
</tr>
</thead>
<tbody>
<tr v-for="(port, index) in convPorts(app.ports)" :key="index">
<td>{{app.Config.Labels[`local.yacht.port.${port.hport}`]}}</td>
<td>{{ port.cport }}</td>
<td>{{ port.hip }}</td>
<td>
Expand Down
16 changes: 16 additions & 0 deletions frontend/src/components/applications/ApplicationsForm.vue
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,22 @@
leave-active-class="animated fadeOutLeft fast-anim"
>
<v-row v-for="(item, index) in form.ports" :key="index">
<v-col>
<ValidationProvider
name="Label"
rules=""
v-slot="{ errors, valid }"
>
<v-text-field
type="string"
label="Label"
placeholder="webui"
v-model="item['label']"
:error-messages="errors"
:success="valid"
></v-text-field>
</ValidationProvider>
</v-col>
<v-col>
<ValidationProvider
name="Container"
Expand Down
58 changes: 36 additions & 22 deletions frontend/src/components/applications/ApplicationsList.vue
Original file line number Diff line number Diff line change
Expand Up @@ -90,28 +90,42 @@
</template>
<template v-slot:item.ports="{ item }">
<ins v-for="(port, index) in convPorts(item.ports)" :key="index">
<v-chip
class="mx-1"
v-if="port.hip == '0.0.0.0'"
color="indigo darken-2"
label
small
:href="'http://' + host_ip + ':' + port.hport"
target="_blank"
><v-icon small class="mr-1">mdi-link-variant</v-icon
>{{ port.hport }}</v-chip
>
<v-chip
class="ma-1"
v-else
color="indigo darken-2"
label
small
:href="'http://' + port.hip + ':' + port.hport"
target="_blank"
><v-icon small class="mr-1">mdi-link-variant</v-icon
>{{ port.hport }}</v-chip
>
<v-tooltip top transition="scale-transition">
<template v-slot:activator="{ on, attrs }">
<v-chip
v-on="on"
v-bind="attrs"
class="mx-1"
v-if="port.hip == '0.0.0.0'"
color="indigo darken-2"
label
small
:href="'http://' + host_ip + ':' + port.hport"
target="_blank"
><v-icon small class="mr-1">mdi-link-variant</v-icon
>{{
item.Config.Labels[`local.yacht.port.${port.hport}`] ||
port.hport
}}</v-chip
>
<v-chip
v-on="on"
v-bind="attrs"
class="ma-1"
v-else
color="indigo darken-2"
label
small
:href="'http://' + port.hip + ':' + port.hport"
target="_blank"
><v-icon small class="mr-1">mdi-link-variant</v-icon
>{{ item.Config.Labels || port.hport }}</v-chip
>
</template>
<span>
{{ port.hport }}
</span>
</v-tooltip>
</ins>
</template>
<template v-slot:item.image="{ item }">
Expand Down
Loading