unet-cli: fix formatting of help text
[project/unetd.git] / scripts / unet-cli
index 96894a3b416d6cdeee03bc04b5a9f2c8e09566e2..f77f113819b6727227a2269d60c7ae0c9326fd96 100755 (executable)
@@ -1,5 +1,7 @@
 #!/usr/bin/env ucode
 
+'use strict';
+
 import { access, basename, dirname, mkstemp, open, writefile } from 'fs';
 
 function assert(cond, message) {
@@ -11,17 +13,17 @@ function assert(cond, message) {
        return true;
 }
 
+let unet_tool = "unet-tool";
 let script_dir = sourcepath(0, true);
+
 if (basename(script_dir) == "scripts") {
        unet_tool = `${dirname(script_dir)}/unet-tool`;
        assert(access(unet_tool, "x"), "unet-tool missing");
-} else {
-       unet_tool = "unet-tool";
 }
 
-args = {};
+let args = {};
 
-defaults = {
+const defaults = {
        port: 51830,
        pex_port: 51831,
        keepalive: 10,
@@ -32,49 +34,49 @@ Usage: ${basename(sourcepath())} [<flags>] <file> <command> [<args>] [<option>=<
 
      Commands:
       - create:                                        Create a new network file
-      - set-config:                                    Change network config parameters
-      - add-host <name>:                               Add a host
-      - add-ssh-host <name> <host>:                    Add a remote OpenWrt host via SSH
-                                               (<host> can contain SSH options as well)
-      - set-host <name>:                               Change host settings
-      - set-ssh-host <name> <host>:                    Update local and remote host settings
-      - add-service <name>:                            Add a service
-      - set-service <name>:                            Change service settings
-      - sign                                           Sign network data
+      - set-config:                            Change network config parameters
+      - add-host <name>:                       Add a host
+      - add-ssh-host <name> <host>:            Add a remote OpenWrt host via SSH
+                                               (<host> can contain SSH options as well)
+      - set-host <name>:                       Change host settings
+      - set-ssh-host <name> <host>:            Update local and remote host settings
+      - add-service <name>:                    Add a service
+      - set-service <name>:                    Change service settings
+      - sign                                   Sign network data
 
      Flags:
-      -p:                                              Print modified JSON instead of updating file
+      -p:                                      Print modified JSON instead of updating file
 
      Options:
       - config options (create, set-config):
-       port=<val>                              set tunnel port (default: ${defaults.port})
-       pex_port=<val>                          set peer-exchange port (default: ${defaults.pex_port})
-       keepalive=<val>                         set keepalive interval (seconds, 0: off, default: ${defaults.keepalive})
-      host options (add-host, add-ssh-host, set-host):
-       key=<val>                               set host public key (required for add-host)
-       port=<val>                              set host tunnel port number
-       groups=[+|-]<val>[,<val>...]            set/add/remove groups that the host is a member of
-       ipaddr=[+|-]<val>[,<val>...]            set/add/remove host ip addresses
-       subnet=[+|-]<val>[,<val>...]            set/add/remove host announced subnets
-       endpoint=<val>                          set host endpoint address
-       gateway=<name>                          set host gateway (using name of other host)
-      ssh host options (add-ssh-host, set-ssh-host)
-       auth_key=<key>                          use <key> as public auth key on the remote host
-       priv_key=<key>                          use <key> as private host key on the remote host (default: generate a new key)
-       interface=<name>                        use <name> as interface in /etc/config/network on the remote host
-       domain=<name>                           use <name> as hosts file domain on the remote host (default: unet)
-       connect=<val>[,<val>...]                set IP addresses that the host will contact for network updates
-       tunnels=<ifname>:<service>[,...]        set active tunnel devices
-      service options (add-service, set-service):
-       type=<val>                              set service type (required for add-service)
-       members=[+|-]<val>[,<val>...]           set/add/remove service member hosts/groups
-      vxlan service options (add-service, set-service):
-       id=<val>                                set VXLAN ID
-       port=<val>                              set VXLAN port
-       mtu=<val>                               set VXLAN device MTU
-       forward_ports=[+|-]<val>[,<val>...]     set members allowed to receive broadcast/multicast/unknown-unicast
-      sign options:
-       upload=<ip>[,<ip>...]                   upload signed file to hosts
+       port=<val>                              set tunnel port (default: ${defaults.port})
+       pex_port=<val>                          set peer-exchange port (default: ${defaults.pex_port})
+       keepalive=<val>                         set keepalive interval (seconds, 0: off, default: ${defaults.keepalive})
+      host options (add-host, add-ssh-host, set-host):
+       key=<val>                               set host public key (required for add-host)
+       port=<val>                              set host tunnel port number
+       groups=[+|-]<val>[,<val>...]            set/add/remove groups that the host is a member of
+       ipaddr=[+|-]<val>[,<val>...]            set/add/remove host ip addresses
+       subnet=[+|-]<val>[,<val>...]            set/add/remove host announced subnets
+       endpoint=<val>                          set host endpoint address
+       gateway=<name>                          set host gateway (using name of other host)
+     - ssh host options (add-ssh-host, set-ssh-host)
+       auth_key=<key>                          use <key> as public auth key on the remote host
+       priv_key=<key>                          use <key> as private host key on the remote host (default: generate a new key)
+       interface=<name>                        use <name> as interface in /etc/config/network on the remote host
+       domain=<name>                           use <name> as hosts file domain on the remote host (default: unet)
+       connect=<val>[,<val>...]                set IP addresses that the host will contact for network updates
+       tunnels=<ifname>:<service>[,...]        set active tunnel devices
+     - service options (add-service, set-service):
+       type=<val>                              set service type (required for add-service)
+       members=[+|-]<val>[,<val>...]           set/add/remove service member hosts/groups
+     - vxlan service options (add-service, set-service):
+       id=<val>                                set VXLAN ID
+       port=<val>                              set VXLAN port
+       mtu=<val>                               set VXLAN device MTU
+       forward_ports=[+|-]<val>[,<val>...]     set members allowed to receive broadcast/multicast/unknown-unicast
+     - sign options:
+       upload=<ip>[,<ip>...]                   upload signed file to hosts
 
 `;
 
@@ -86,10 +88,10 @@ function usage() {
 if (length(ARGV) < 2)
        exit(usage());
 
-file = shift(ARGV);
-command = shift(ARGV);
+let file = shift(ARGV);
+let command = shift(ARGV);
 
-field_types = {
+const field_types = {
        int: function(object, name, val) {
                object[name] = int(val);
        },
@@ -121,7 +123,7 @@ field_types = {
        },
 };
 
-service_field_types = {
+const service_field_types = {
        vxlan: {
                id: "int",
                port: "int",
@@ -130,7 +132,7 @@ service_field_types = {
        },
 };
 
-ssh_script = `
+const ssh_script = `
 
 set_list() {
        local field="$1"
@@ -180,12 +182,11 @@ reload_config
 ifup $INTERFACE
 `;
 
-args = {};
-print_only = false;
+let print_only = false;
 
 function fetch_args() {
-       for (arg in ARGV) {
-               vals = match(arg, /^(.[[:alnum:]_-]*)=(.*)$/);
+       for (let arg in ARGV) {
+               let vals = match(arg, /^(.[[:alnum:]_-]*)=(.*)$/);
                assert(vals, `Invalid argument: ${arg}`);
                args[vals[1]] = vals[2]
        }
@@ -209,13 +210,11 @@ function set_field(typename, object, name, val) {
 }
 
 function set_fields(object, list) {
-       for (f in list)
+       for (let f in list)
                set_field(list[f], object, f, args[f]);
 }
 
-function set_host(name) {
-       let host = net_data.hosts[name];
-
+function set_host(host) {
        set_fields(host, {
                key: "string",
                endpoint: "string",
@@ -227,9 +226,7 @@ function set_host(name) {
        });
 }
 
-function set_service(name) {
-       let service = net_data.services[name];
-
+function set_service(service) {
        set_fields(service, {
                type: "string",
                members: "array",
@@ -269,16 +266,16 @@ function sync_ssh_host(host) {
        fh.flush();
        fh.seek();
 
-       fh2 = mkstemp();
+       let fh2 = mkstemp();
        system(`ssh ${host} sh <&${fh.fileno()} >&${fh2.fileno()}`);
        fh.close();
 
-       data = {};
+       let data = {}, line;
 
        fh2.seek();
        while (line = fh2.read("line")) {
                let vals = match(line, /^(.[[:alnum:]_-]*)=(.*)\n$/);
-               assert(vals, `Invalid argument: ${arg}`);
+               assert(vals, `Invalid argument: ${line}`);
                data[vals[1]] = vals[2]
        }
        fh2.close();
@@ -289,7 +286,7 @@ function sync_ssh_host(host) {
 }
 
 while (substr(ARGV[0], 0, 1) == "-") {
-       opt = shift(ARGV);
+       let opt = shift(ARGV);
        if (opt == "--")
                break;
        else if (opt == "-p")
@@ -298,6 +295,8 @@ while (substr(ARGV[0], 0, 1) == "-") {
                exit(usage());
 }
 
+let hostname, ssh_host, servicename;
+
 if (command in [ "add-host", "set-host", "add-ssh-host", "set-ssh-host" ]) {
        hostname = shift(ARGV);
        assert(hostname, "Missing host name argument");
@@ -320,6 +319,8 @@ if (command in [ "add-ssh-host", "set-ssh-host" ]) {
        command = replace(command, "ssh-", "");
 }
 
+let net_data;
+
 if (command == "create") {
        net_data = {
                config: {},
@@ -327,7 +328,7 @@ if (command == "create") {
                services: {}
        };
 } else {
-       fh = open(file);
+       let fh = open(file);
        assert(fh, `Could not open input file ${file}`);
 
        try {
@@ -338,20 +339,19 @@ if (command == "create") {
 }
 
 if (command == "create") {
-       for (key, val in defaults)
+       for (let key, val in defaults)
                args[key] ??= `${val}`;
        if (!access(`${file}.key`))
                system(`${unet_tool} -G > ${file}.key`);
 }
 
 if (command == "sign") {
-       ret = system(`${unet_tool} -S -K ${file}.key -o ${file}.bin ${file}`);
+       let ret = system(`${unet_tool} -S -K ${file}.key -o ${file}.bin ${file}`);
        if (ret != 0)
                exit(ret);
 
        if (args.upload) {
-               hosts = split(args.upload, ",");
-               for (host in hosts) {
+               for (let host in split(args.upload, ",")) {
                        warn(`Uploading ${file}.bin to ${host}\n`);
                        ret = system(`${unet_tool} -U ${host} -K ${file}.key ${file}.bin`);
                        if (ret)
@@ -374,12 +374,12 @@ case 'set-config':
 case 'add-host':
        net_data.hosts[hostname] = {};
        assert(args.key, "Missing host key");
-       set_host(hostname);
+       set_host(net_data.hosts[hostname]);
        break;
 
 case 'set-host':
        assert(net_data.hosts[hostname], `Host '${hostname}' does not exist`);
-       set_host(hostname);
+       set_host(net_data.hosts[hostname]);
        break;
 
 case 'add-service':
@@ -388,19 +388,20 @@ case 'add-service':
                members: [],
        };
        assert(args.type, "Missing service type");
-       set_service(servicename);
+       set_service(net_data.services[servicename]);
        break;
 
 case 'set-service':
        assert(net_data.services[servicename], `Service '${servicename}' does not exist`);
-       set_service(servicename);
+       set_service(net_data.services[servicename]);
        break;
 
 default:
        assert(false, "Unknown command");
 }
 
-net_data_json = sprintf("%.J\n", net_data);
+const net_data_json = sprintf("%.J\n", net_data);
+
 if (print_only)
        print(net_data_json);
 else