wip: 2024.08.16 14:07:25
This commit is contained in:
parent
7557f75579
commit
775b4ca6e7
12 changed files with 203 additions and 24 deletions
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
|
@ -0,0 +1 @@
|
||||||
|
result
|
11
flake.nix
11
flake.nix
|
@ -9,16 +9,19 @@
|
||||||
{ nixpkgs, ... }:
|
{ nixpkgs, ... }:
|
||||||
let
|
let
|
||||||
inherit (nixpkgs.lib) genAttrs;
|
inherit (nixpkgs.lib) genAttrs;
|
||||||
forAllSystems =
|
systems = [
|
||||||
f:
|
|
||||||
genAttrs [
|
|
||||||
"x86_64-linux"
|
"x86_64-linux"
|
||||||
"x86_64-darwin"
|
"x86_64-darwin"
|
||||||
"aarch64-linux"
|
"aarch64-linux"
|
||||||
"aarch64-darwin"
|
"aarch64-darwin"
|
||||||
] (system: f nixpkgs.legacyPackages.${system});
|
];
|
||||||
|
forAllSystems = f: genAttrs systems (system: f (import nixpkgs { inherit system; }));
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
|
packages = forAllSystems (pkgs: rec {
|
||||||
|
default = pkgs.callPackage ./meta.nix {inherit tunnel;};
|
||||||
|
tunnel = pkgs.callPackage ./tunnel-go { };
|
||||||
|
});
|
||||||
devShells = forAllSystems (pkgs: {
|
devShells = forAllSystems (pkgs: {
|
||||||
default = pkgs.mkShell {
|
default = pkgs.mkShell {
|
||||||
packages = with pkgs; [
|
packages = with pkgs; [
|
||||||
|
|
30
meta.nix
Normal file
30
meta.nix
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
{
|
||||||
|
lib,
|
||||||
|
stdenvNoCC,
|
||||||
|
|
||||||
|
# packages
|
||||||
|
tunnel,
|
||||||
|
...
|
||||||
|
}:stdenvNoCC.mkDerivation (finalAttrs: {
|
||||||
|
pname = "meta";
|
||||||
|
version = "unstable";
|
||||||
|
|
||||||
|
# src =
|
||||||
|
buildInputs = [
|
||||||
|
tunnel
|
||||||
|
];
|
||||||
|
|
||||||
|
phases = [ "installPhase"];
|
||||||
|
|
||||||
|
installPhase = ''
|
||||||
|
mkdir -p $out/bin
|
||||||
|
ln -s ${tunnel}/bin/tunnel $out/bin
|
||||||
|
'';
|
||||||
|
|
||||||
|
meta = {
|
||||||
|
description = "meta package for utils";
|
||||||
|
homepage = "https://git.dayl.in/daylin/utils";
|
||||||
|
license = lib.licenses.mit;
|
||||||
|
maintainers = with lib.maintainers; [ daylinmorgan ];
|
||||||
|
};
|
||||||
|
})
|
|
@ -13,12 +13,9 @@ buildGoModule rec {
|
||||||
version = "unstable";
|
version = "unstable";
|
||||||
|
|
||||||
src = cleanSource ./.;
|
src = cleanSource ./.;
|
||||||
vendorHash = "";
|
vendorHash = "sha256-PwZJMEVaPHqZs7bM+9XLxVA36GfV3EN6bja86hkfO90=";
|
||||||
|
|
||||||
nativeBuildInputs = [
|
nativeBuildInputs = [ installShellFiles makeWrapper ];
|
||||||
installShellFiles
|
|
||||||
makeWrapper
|
|
||||||
];
|
|
||||||
|
|
||||||
postInstall = ''
|
postInstall = ''
|
||||||
installShellCompletion --cmd ${pname} \
|
installShellCompletion --cmd ${pname} \
|
||||||
|
|
|
@ -2,11 +2,13 @@ package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"io/fs"
|
||||||
"log"
|
"log"
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
|
"path/filepath"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"github.com/bitfield/script"
|
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -40,28 +42,47 @@ func tunnelUp() {
|
||||||
logFail(connectPort(), "failed to connect to host: %s with port: %d", host, port)
|
logFail(connectPort(), "failed to connect to host: %s with port: %d", host, port)
|
||||||
}
|
}
|
||||||
|
|
||||||
func tunnelDown() { logFail(deactivateSshControl(), "failed to disable ssh control %s", host) }
|
func tunnelDown() {
|
||||||
|
logFail(deactivateSshControl(), "failed to disable ssh control %s", host)
|
||||||
|
}
|
||||||
|
|
||||||
|
func getControlSockets(files []fs.DirEntry) (ret []string) {
|
||||||
|
for _, f := range files {
|
||||||
|
if strings.HasPrefix(f.Name(), "control") {
|
||||||
|
ret = append(ret, f.Name())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
func tunnelShow() {
|
func tunnelShow() {
|
||||||
script.ListFiles("/home/daylin/.ssh").Stdout()
|
files, err := os.ReadDir(sshDir)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
controls := getControlSockets(files)
|
||||||
|
fmt.Printf("%d active connections\n", len(controls))
|
||||||
|
if len(controls) > 0 {
|
||||||
|
fmt.Println("hosts:")
|
||||||
|
for _, c := range controls {
|
||||||
|
fmt.Printf(" %s\n", strings.Split(c, "-")[1])
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
sshDir = filepath.Join(os.Getenv("HOME"), ".ssh")
|
||||||
rootCmd = &cobra.Command{Use: "tunnel", Short: "control ssh tunnels"}
|
rootCmd = &cobra.Command{Use: "tunnel", Short: "control ssh tunnels"}
|
||||||
upCmd = genSubCmd("up hostname [flags]", "activate ssh tunnel", tunnelUp)
|
upCmd = genSubCmd("up hostname [flags]", "activate ssh tunnel", tunnelUp)
|
||||||
downCmd = genSubCmd("down hostname [flags]", "deactivate ssh tunnel", tunnelDown)
|
downCmd = genSubCmd("down hostname [flags]", "deactivate ssh tunnel", tunnelDown)
|
||||||
showCmd = &cobra.Command{Use: "show", Short: "show activate tunnels", Run: func(cmd *cobra.Command, args []string) { tunnelShow() }}
|
showCmd = &cobra.Command{Use: "show", Short: "show activate tunnels", Run: func(cmd *cobra.Command, args []string) { tunnelShow() }}
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
port uint64
|
port uint64
|
||||||
host string
|
host string
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
rootCmd.CompletionOptions.HiddenDefaultCmd = true
|
rootCmd.CompletionOptions.HiddenDefaultCmd = true
|
||||||
rootCmd.AddCommand(upCmd)
|
rootCmd.AddCommand(upCmd, downCmd, showCmd)
|
||||||
rootCmd.AddCommand(downCmd)
|
|
||||||
rootCmd.AddCommand(showCmd)
|
|
||||||
upCmd.Flags().Uint64VarP(&port, "port", "p", 0, "port number")
|
upCmd.Flags().Uint64VarP(&port, "port", "p", 0, "port number")
|
||||||
upCmd.MarkFlagRequired("port")
|
upCmd.MarkFlagRequired("port")
|
||||||
}
|
}
|
||||||
|
|
3
tunnel-nim/.gitignore
vendored
Normal file
3
tunnel-nim/.gitignore
vendored
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
nimbledeps/
|
||||||
|
nimble.paths
|
||||||
|
nimble.develop
|
11
tunnel-nim/config.nims
Normal file
11
tunnel-nim/config.nims
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
# begin Nimble config (version 2)
|
||||||
|
--noNimblePath
|
||||||
|
when withDir(thisDir(), system.fileExists("nimble.paths")):
|
||||||
|
include "nimble.paths"
|
||||||
|
# end Nimble config
|
||||||
|
|
||||||
|
task updateLock, "update nix lock.json":
|
||||||
|
exec "nimble lock -l"
|
||||||
|
exec "nix run 'github:daylinmorgan/nnl' -- nimble.lock -o:lock.json"
|
||||||
|
|
||||||
|
|
14
tunnel-nim/default.nix
Normal file
14
tunnel-nim/default.nix
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
{
|
||||||
|
lib,
|
||||||
|
buildNimPackage,
|
||||||
|
makeWrapper,
|
||||||
|
}:
|
||||||
|
buildNimPackage {
|
||||||
|
pname = "tunnel";
|
||||||
|
version = "unstable";
|
||||||
|
|
||||||
|
src = lib.cleanSource ./.;
|
||||||
|
lockFile = ./lock.json;
|
||||||
|
nativeBuildInputs = [ makeWrapper ];
|
||||||
|
doCheck = false;
|
||||||
|
}
|
16
tunnel-nim/lock.json
Normal file
16
tunnel-nim/lock.json
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
{
|
||||||
|
"depends": [
|
||||||
|
{
|
||||||
|
"method": "fetchzip",
|
||||||
|
"path": "/nix/store/5a5aafd2vb3yb39ha5hbz8im9al9shjg-source",
|
||||||
|
"rev": "0e7b3b3a1fa77c448d3681c5fdf85197844cb7e4",
|
||||||
|
"sha256": "1c5xdxmgvibbrkn53svawp3wbwb0ylg3fnzbpgiadgnnpz3cdixz",
|
||||||
|
"srcDir": "",
|
||||||
|
"url": "https://github.com/c-blake/cligen/archive/0e7b3b3a1fa77c448d3681c5fdf85197844cb7e4.tar.gz",
|
||||||
|
"subDir": "",
|
||||||
|
"packages": [
|
||||||
|
"cligen"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
16
tunnel-nim/nimble.lock
Normal file
16
tunnel-nim/nimble.lock
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
{
|
||||||
|
"version": 2,
|
||||||
|
"packages": {
|
||||||
|
"cligen": {
|
||||||
|
"version": "1.7.3",
|
||||||
|
"vcsRevision": "0e7b3b3a1fa77c448d3681c5fdf85197844cb7e4",
|
||||||
|
"url": "https://github.com/c-blake/cligen.git",
|
||||||
|
"downloadMethod": "git",
|
||||||
|
"dependencies": [],
|
||||||
|
"checksums": {
|
||||||
|
"sha1": "5a082835594887c0fdaea17dbfd2d3a2e744a2a9"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"tasks": {}
|
||||||
|
}
|
52
tunnel-nim/tunnel.nim
Normal file
52
tunnel-nim/tunnel.nim
Normal file
|
@ -0,0 +1,52 @@
|
||||||
|
import std/[os, osproc, sequtils, strformat, strutils, sugar]
|
||||||
|
|
||||||
|
import cligen
|
||||||
|
|
||||||
|
proc checkHost(host: seq[string]): string =
|
||||||
|
case host.len:
|
||||||
|
of 0: quit "expected hostname"
|
||||||
|
of 1: return host[0]
|
||||||
|
else: quit "expected one positinal argument"
|
||||||
|
|
||||||
|
|
||||||
|
proc check(name: string): bool =
|
||||||
|
(execCmd &"ssh -O check {name}") == 0
|
||||||
|
proc startSsh(name: string) =
|
||||||
|
discard execCmd &"ssh -M -f -N {name}"
|
||||||
|
proc activateTunnel(name: string, port: int): int =
|
||||||
|
execCmd &"""ssh -fNL "{port}:localhost:{port}" {name}"""
|
||||||
|
proc exitSsh(name: string):int =
|
||||||
|
execCmd &"ssh -O exit {name}"
|
||||||
|
|
||||||
|
proc up(port: int, host: seq[string]) =
|
||||||
|
## activate a tunnel
|
||||||
|
let name = checkHost host
|
||||||
|
echo "activating connection to", name
|
||||||
|
if not check(name):
|
||||||
|
startSsh(name)
|
||||||
|
quit activateTunnel(name, port)
|
||||||
|
|
||||||
|
|
||||||
|
proc down(host: seq[string]) =
|
||||||
|
## disable all tunnels
|
||||||
|
let name = checkHost host
|
||||||
|
echo "deactivating connection to", name
|
||||||
|
quit exitSsh(name)
|
||||||
|
|
||||||
|
proc show() =
|
||||||
|
## show active connections
|
||||||
|
let sshDir = (getEnv "HOME") / ".ssh"
|
||||||
|
let controllers =
|
||||||
|
collect(for _,p in walkDir(sshDir): p)
|
||||||
|
.map(extractFilename)
|
||||||
|
.filterIt(it.startsWith("control"))
|
||||||
|
echo &"{controllers.len} active connections"
|
||||||
|
if controllers.len == 0: quit 0
|
||||||
|
echo "hosts:"
|
||||||
|
echo controllers.mapIt(" " & it.split('-')[1]).join("\n")
|
||||||
|
|
||||||
|
const
|
||||||
|
hostUsage = "$command [flags] hostname\n${doc}Options:\n$options"
|
||||||
|
usage = "$command [flags]\n${doc}Options:\n$options"
|
||||||
|
|
||||||
|
dispatchMulti([up, usage=hostUsage], [down, usage=hostUsage], [show, usage=usage])
|
15
tunnel-nim/tunnel.nimble
Normal file
15
tunnel-nim/tunnel.nimble
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
# Package
|
||||||
|
|
||||||
|
version = "0.1.0"
|
||||||
|
author = "Daylin Morgan"
|
||||||
|
description = "A new awesome nimble package"
|
||||||
|
license = "MIT"
|
||||||
|
srcDir = "."
|
||||||
|
bin = @["tunnel"]
|
||||||
|
|
||||||
|
|
||||||
|
# Dependencies
|
||||||
|
requires "nim >= 2.0.8"
|
||||||
|
requires "cligen"
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue