Commit 10ae05ee authored by jan.koester's avatar jan.koester
Browse files

test

parent a7aee5ba
Loading
Loading
Loading
Loading
+4 −3
Changes for modules/containers/containers.cpp: 4 added lines, 3 removed lines.
Original line number Diff line number Diff line
@@ -31,7 +31,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *   list                  -> {containers, images, jobs, bridges} or
 *                            {unavailable} when containerd isn't there
 *       containers: [{name, image, state, pid, started, exitCode, restarts,
 *           error?, network, address?, lease?, autostart, restart, memory, tasks}]
 *           error?, network, address?, vlan?, lease?, autostart, restart, memory, tasks}]
 *       images: [{image, id, digest, size, layers, created, pulled,
 *           architecture, entrypoint?, cmd?, workdir?, user?, env[], ports[],
 *           volumes[], usedBy[]}]
@@ -41,7 +41,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *   create {container}    a container: name, image, entrypoint[], args[],
 *   update {name, container}   env[], user, workdir, hostname, boot,
 *                         autostart, restart, network, bridge, address,
 *                         gateway, mac, dns[], binds[], tmpfs[], devices[], readOnly,
 *                         gateway, mac, vlan (0: none), dns[], binds[], tmpfs[], devices[], readOnly,
 *                         memoryMax, tasksMax, capabilities[],
 *                         dropCapabilities[] (update: name renames)
 *   delete {name}         (its files go in the background)
@@ -95,7 +95,7 @@ using Fields = std::vector<std::pair<std::string, std::string>>;

const std::set<std::string> Flags = {"boot", "autostart", "read_only"};
const std::set<std::string> Numbers = {"pid", "started", "exit_code", "restarts", "memory", "tasks", "size", "layers",
                                       "pulled", "memory_max", "tasks_max", "seconds", "finished"};
                                       "pulled", "memory_max", "tasks_max", "seconds", "finished", "vlan"};
// repeated keys -> JSON list names
const std::vector<std::pair<std::string, std::string>> Lists = {
    {"entrypoint", "entrypoint"}, {"arg", "args"}, {"env", "env"}, {"dns", "dns"}, {"bind", "binds"},
@@ -262,6 +262,7 @@ std::string settingsFields(json_object *c, Fields &f, bool create) {
    text("address", "address");
    text("gateway", "gateway");
    text("mac", "mac");
    number("vlan", "vlan");
    flag("readOnly", "read_only");
    number("memoryMax", "memory_max");
    number("tasksMax", "tasks_max");
+13 −4
Changes for www/modules/containers.js: 13 added lines, 4 removed lines.
Original line number Diff line number Diff line
@@ -38,6 +38,10 @@
    'Only loopback': 'Nur Loopback', 'Own address in a bridge': 'Eigene Adresse in einer Bridge',
    'Bridge': 'Bridge', 'Address (CIDR)': 'Adresse (CIDR)', 'Gateway': 'Gateway', 'DNS servers': 'DNS-Server',
    'Address from DHCP': 'Adresse per DHCP', 'MAC address': 'MAC-Adresse',
    'VLAN (0: none)': 'VLAN (0: keins)', 'VLAN {0}': 'VLAN {0}',
    'The VLAN must be between 0 and 4094.': 'Das VLAN muss zwischen 0 und 4094 liegen.',
    'With a VLAN the container is an access port of it: the bridge filters VLANs (its other ports stay untagged), its uplinks carry the VLAN tagged, so the switch port must too.':
      'Mit einem VLAN ist der Container ein Access-Port davon: die Bridge filtert VLANs (ihre anderen Ports bleiben ungetaggt), ihre Uplinks führen das VLAN getaggt, der Switch-Port muss es also auch.',
    'default: made from the name (stays the same)': 'Vorgabe: aus dem Namen (bleibt gleich)',
    'Devices (one per line, e.g. /dev/dri for an Intel GPU)': 'Geräte (eines pro Zeile, z. B. /dev/dri für eine Intel-GPU)',
    'The container may use only these devices (and /dev/null & co.); its user gets their groups (render, video).':
@@ -296,7 +300,9 @@
            h('label', {}, t('Bridge'), h('select', {name: 'bridge'},
              bridges.map(b => h('option', {value: b, selected: b === c.bridge}, b)),
              c.bridge && !bridges.includes(c.bridge) ? h('option', {value: c.bridge, selected: true}, c.bridge) : null)),
            h('label', {}, t('MAC address'), h('input', {name: 'mac', value: c.mac || '', placeholder: t('default: made from the name (stays the same)')}))),
            h('label', {}, t('MAC address'), h('input', {name: 'mac', value: c.mac || '', placeholder: t('default: made from the name (stays the same)')})),
            h('label', {}, t('VLAN (0: none)'), h('input', {name: 'vlan', type: 'number', min: 0, max: 4094, value: c.vlan || 0}))),
          h('p', {class: 'hint'}, t('With a VLAN the container is an access port of it: the bridge filters VLANs (its other ports stay untagged), its uplinks carry the VLAN tagged, so the switch port must too.')),
          h('label', {class: 'check'}, dhcp, t('Address from DHCP')),
          staticBox,
          bridges.length ? null : h('p', {class: 'hint'}, t('No bridge yet: create one under Network.')));
@@ -370,11 +376,13 @@
      },
      onSubmit: async d => {
        const mem = Number(d.memoryMax) || 0;
        const vlan = d.network === 'bridge' ? Number(d.vlan) || 0 : 0;
        if (!Number.isInteger(vlan) || vlan < 0 || vlan > 4094) throw new Error(t('The VLAN must be between 0 and 4094.'));
        const container = {
          name: d.name.trim(), image: d.image, autostart: d.autostart, restart: d.restart, network: d.network,
          bridge: d.network === 'bridge' ? (d.bridge || '') : '',
          address: d.network !== 'bridge' ? '' : d.dhcp ? 'dhcp' : d.address.trim(),
          gateway: d.network === 'bridge' && !d.dhcp ? d.gateway.trim() : '', mac: d.network === 'bridge' ? d.mac.trim() : '',
          gateway: d.network === 'bridge' && !d.dhcp ? d.gateway.trim() : '', mac: d.network === 'bridge' ? d.mac.trim() : '', vlan,
          dns: words(d.dns), args: words(d.args),
          entrypoint: words(d.entrypoint), env: lines(d.env), binds: lines(d.binds), tmpfs: lines(d.tmpfs), devices: lines(d.devices),
          user: d.user.trim(), workdir: d.workdir.trim(), hostname: d.hostname.trim(),
@@ -421,8 +429,9 @@
          {title: t('Image'), render: c => h('span', {class: 'mono'}, c.image || '')},
          {title: t('State'), render: stateCell},
          {title: t('Network'), render: c => c.network !== 'bridge' ? t(c.network || '')
            : c.address === 'dhcp' ? h('span', {class: 'mono'}, c.lease ? t('DHCP: {0}', c.lease) : t('DHCP'))
            : h('span', {class: 'mono'}, c.address || t('bridge'))},
            : [c.address === 'dhcp' ? h('span', {class: 'mono'}, c.lease ? t('DHCP: {0}', c.lease) : t('DHCP'))
                                    : h('span', {class: 'mono'}, c.address || t('bridge')),
               c.vlan ? [' ', h('span', {class: 'badge'}, t('VLAN {0}', c.vlan))] : null]},
          {title: t('Memory'), render: c => c.state === 'running' && c.memory ? mib(c.memory) : ''},
          {title: '', class: 'actions', render: c => {
            const up = c.state === 'running' || c.state === 'starting' || c.state === 'stopping';