mirror of
https://github.com/jesseduffield/lazydocker.git
synced 2026-07-25 08:31:03 +00:00
Merge 0ca4956aed into 4e2f26b21e
This commit is contained in:
commit
a8693ed8c7
8 changed files with 53 additions and 101 deletions
6
.github/workflows/cd.yml
vendored
6
.github/workflows/cd.yml
vendored
|
|
@ -10,15 +10,15 @@ jobs:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout code
|
- name: Checkout code
|
||||||
uses: actions/checkout@v2
|
uses: actions/checkout@v4
|
||||||
- name: Unshallow repo
|
- name: Unshallow repo
|
||||||
run: git fetch --prune --unshallow
|
run: git fetch --prune --unshallow
|
||||||
- name: Setup Go
|
- name: Setup Go
|
||||||
uses: actions/setup-go@v1
|
uses: actions/setup-go@v4
|
||||||
with:
|
with:
|
||||||
go-version: 1.21.x
|
go-version: 1.21.x
|
||||||
- name: Run goreleaser
|
- name: Run goreleaser
|
||||||
uses: goreleaser/goreleaser-action@v1
|
uses: goreleaser/goreleaser-action@v5
|
||||||
with:
|
with:
|
||||||
distribution: goreleaser
|
distribution: goreleaser
|
||||||
version: v1.17.2
|
version: v1.17.2
|
||||||
|
|
|
||||||
24
.github/workflows/ci.yml
vendored
24
.github/workflows/ci.yml
vendored
|
|
@ -23,13 +23,13 @@ jobs:
|
||||||
GOFLAGS: -mod=vendor
|
GOFLAGS: -mod=vendor
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout code
|
- name: Checkout code
|
||||||
uses: actions/checkout@v2
|
uses: actions/checkout@v4
|
||||||
- name: Setup Go
|
- name: Setup Go
|
||||||
uses: actions/setup-go@v1
|
uses: actions/setup-go@v4
|
||||||
with:
|
with:
|
||||||
go-version: 1.21.x
|
go-version: 1.21.x
|
||||||
- name: Cache build
|
- name: Cache build
|
||||||
uses: actions/cache@v1
|
uses: actions/cache@v4
|
||||||
with:
|
with:
|
||||||
path: ~/.cache/go-build
|
path: ~/.cache/go-build
|
||||||
key: ${{runner.os}}-go-${{hashFiles('**/go.sum')}}-test
|
key: ${{runner.os}}-go-${{hashFiles('**/go.sum')}}-test
|
||||||
|
|
@ -45,13 +45,13 @@ jobs:
|
||||||
GOARCH: amd64
|
GOARCH: amd64
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout code
|
- name: Checkout code
|
||||||
uses: actions/checkout@v2
|
uses: actions/checkout@v4
|
||||||
- name: Setup Go
|
- name: Setup Go
|
||||||
uses: actions/setup-go@v1
|
uses: actions/setup-go@v4
|
||||||
with:
|
with:
|
||||||
go-version: 1.21.x
|
go-version: 1.21.x
|
||||||
- name: Cache build
|
- name: Cache build
|
||||||
uses: actions/cache@v1
|
uses: actions/cache@v4
|
||||||
with:
|
with:
|
||||||
path: ~/.cache/go-build
|
path: ~/.cache/go-build
|
||||||
key: ${{runner.os}}-go-${{hashFiles('**/go.sum')}}-build
|
key: ${{runner.os}}-go-${{hashFiles('**/go.sum')}}-build
|
||||||
|
|
@ -73,13 +73,13 @@ jobs:
|
||||||
GOARCH: amd64
|
GOARCH: amd64
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout code
|
- name: Checkout code
|
||||||
uses: actions/checkout@v2
|
uses: actions/checkout@v4
|
||||||
- name: Setup Go
|
- name: Setup Go
|
||||||
uses: actions/setup-go@v1
|
uses: actions/setup-go@v4
|
||||||
with:
|
with:
|
||||||
go-version: 1.21.x
|
go-version: 1.21.x
|
||||||
- name: Cache build
|
- name: Cache build
|
||||||
uses: actions/cache@v1
|
uses: actions/cache@v4
|
||||||
with:
|
with:
|
||||||
path: |
|
path: |
|
||||||
~/.cache/go-build
|
~/.cache/go-build
|
||||||
|
|
@ -100,13 +100,13 @@ jobs:
|
||||||
GOFLAGS: -mod=vendor
|
GOFLAGS: -mod=vendor
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout code
|
- name: Checkout code
|
||||||
uses: actions/checkout@v2
|
uses: actions/checkout@v4
|
||||||
- name: Setup Go
|
- name: Setup Go
|
||||||
uses: actions/setup-go@v1
|
uses: actions/setup-go@v4
|
||||||
with:
|
with:
|
||||||
go-version: 1.21.x
|
go-version: 1.21.x
|
||||||
- name: Cache build
|
- name: Cache build
|
||||||
uses: actions/cache@v1
|
uses: actions/cache@v4
|
||||||
with:
|
with:
|
||||||
path: ~/.cache/go-build
|
path: ~/.cache/go-build
|
||||||
key: ${{runner.os}}-go-${{hashFiles('**/go.sum')}}-test
|
key: ${{runner.os}}-go-${{hashFiles('**/go.sum')}}-test
|
||||||
|
|
|
||||||
2
.github/workflows/sponsors.yml
vendored
2
.github/workflows/sponsors.yml
vendored
|
|
@ -9,7 +9,7 @@ jobs:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout 🛎️
|
- name: Checkout 🛎️
|
||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
- name: Generate Sponsors 💖
|
- name: Generate Sponsors 💖
|
||||||
uses: JamesIves/github-sponsors-readme-action@v1.2.2
|
uses: JamesIves/github-sponsors-readme-action@v1.2.2
|
||||||
|
|
|
||||||
|
|
@ -1,13 +1,11 @@
|
||||||
linters:
|
linters:
|
||||||
disable:
|
|
||||||
- structcheck # gives false positives
|
|
||||||
enable:
|
enable:
|
||||||
- gofumpt
|
- gofumpt
|
||||||
- thelper
|
- thelper
|
||||||
- goimports
|
- goimports
|
||||||
- tparallel
|
- tparallel
|
||||||
- wastedassign
|
- wastedassign
|
||||||
- exportloopref
|
- copyloopvar
|
||||||
- unparam
|
- unparam
|
||||||
- prealloc
|
- prealloc
|
||||||
- unconvert
|
- unconvert
|
||||||
|
|
|
||||||
48
README.md
48
README.md
File diff suppressed because one or more lines are too long
|
|
@ -71,33 +71,30 @@ func (c *DockerCommand) NewCommandObject(obj CommandObject) CommandObject {
|
||||||
return defaultObj
|
return defaultObj
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewDockerCommand it runs docker commands
|
// NewDockerCommand creates a DockerCommand struct that wraps the docker client.
|
||||||
|
// Able to run docker commands and handles SSH docker hosts
|
||||||
func NewDockerCommand(log *logrus.Entry, osCommand *OSCommand, tr *i18n.TranslationSet, config *config.AppConfig, errorChan chan error) (*DockerCommand, error) {
|
func NewDockerCommand(log *logrus.Entry, osCommand *OSCommand, tr *i18n.TranslationSet, config *config.AppConfig, errorChan chan error) (*DockerCommand, error) {
|
||||||
dockerHost, err := determineDockerHost()
|
dockerHost, err := determineDockerHost()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ogLog.Printf("> could not determine host %v", err)
|
ogLog.Printf("> could not determine host %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// NOTE: Inject the determined docker host to the environment. This allows the
|
tunnelResult, err := ssh.NewSSHHandler(osCommand).HandleSSHDockerHost(dockerHost)
|
||||||
// `SSHHandler.HandleSSHDockerHost()` to create a local unix socket tunneled
|
|
||||||
// over SSH to the specified ssh host.
|
|
||||||
if strings.HasPrefix(dockerHost, "ssh://") {
|
|
||||||
os.Setenv(dockerHostEnvKey, dockerHost)
|
|
||||||
}
|
|
||||||
|
|
||||||
tunnelCloser, err := ssh.NewSSHHandler(osCommand).HandleSSHDockerHost()
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ogLog.Fatal(err)
|
ogLog.Fatal(err)
|
||||||
}
|
}
|
||||||
|
// If we created a tunnel to the remote ssh host, we then override the dockerhost to point to the tunnel
|
||||||
// Retrieve the docker host from the environment which could have been set by
|
if tunnelResult.Created {
|
||||||
// the `SSHHandler.HandleSSHDockerHost()` and override `dockerHost`.
|
dockerHost = tunnelResult.SocketPath
|
||||||
dockerHostFromEnv := os.Getenv(dockerHostEnvKey)
|
|
||||||
if dockerHostFromEnv != "" {
|
|
||||||
dockerHost = dockerHostFromEnv
|
|
||||||
}
|
}
|
||||||
|
|
||||||
cli, err := client.NewClientWithOpts(client.FromEnv, client.WithVersion(APIVersion), client.WithHost(dockerHost))
|
clientOpts := []client.Opt{
|
||||||
|
client.WithTLSClientConfigFromEnv(),
|
||||||
|
client.WithVersion(APIVersion),
|
||||||
|
client.WithHost(dockerHost),
|
||||||
|
}
|
||||||
|
|
||||||
|
cli, err := client.NewClientWithOpts(clientOpts...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ogLog.Fatal(err)
|
ogLog.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
@ -110,7 +107,7 @@ func NewDockerCommand(log *logrus.Entry, osCommand *OSCommand, tr *i18n.Translat
|
||||||
Client: cli,
|
Client: cli,
|
||||||
ErrorChan: errorChan,
|
ErrorChan: errorChan,
|
||||||
InDockerComposeProject: true,
|
InDockerComposeProject: true,
|
||||||
Closers: []io.Closer{tunnelCloser},
|
Closers: []io.Closer{tunnelResult.Closer},
|
||||||
}
|
}
|
||||||
|
|
||||||
dockerCommand.setDockerComposeCommand(config)
|
dockerCommand.setDockerComposeCommand(config)
|
||||||
|
|
|
||||||
|
|
@ -42,31 +42,36 @@ func NewSSHHandler(oSCommand CmdKiller) *SSHHandler {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type TunnelResult struct {
|
||||||
|
Closer io.Closer
|
||||||
|
SocketPath string
|
||||||
|
Created bool
|
||||||
|
}
|
||||||
|
|
||||||
// HandleSSHDockerHost overrides the DOCKER_HOST environment variable
|
// HandleSSHDockerHost overrides the DOCKER_HOST environment variable
|
||||||
// to point towards a local unix socket tunneled over SSH to the specified ssh host.
|
// to point towards a local unix socket tunneled over SSH to the specified ssh host.
|
||||||
func (self *SSHHandler) HandleSSHDockerHost() (io.Closer, error) {
|
func (self *SSHHandler) HandleSSHDockerHost(dockerHost string) (TunnelResult, error) {
|
||||||
const key = "DOCKER_HOST"
|
u, err := url.Parse(dockerHost)
|
||||||
ctx := context.Background()
|
|
||||||
u, err := url.Parse(self.getenv(key))
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// if no or an invalid docker host is specified, continue nominally
|
// if no or an invalid docker host is specified, continue nominally
|
||||||
return noopCloser{}, nil
|
return TunnelResult{Closer: noopCloser{}}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// if the docker host scheme is "ssh", forward the docker socket before creating the client
|
// if the docker host scheme is "ssh", forward the docker socket before creating the client
|
||||||
if u.Scheme == "ssh" {
|
if u.Scheme == "ssh" {
|
||||||
tunnel, err := self.createDockerHostTunnel(ctx, u.Host)
|
ctx := context.Background()
|
||||||
|
tunnel, err := self.createDockerHostTunnel(ctx, u.String())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return noopCloser{}, fmt.Errorf("tunnel ssh docker host: %w", err)
|
return TunnelResult{Closer: noopCloser{}}, fmt.Errorf("tunnel ssh docker host: %w", err)
|
||||||
}
|
|
||||||
err = self.setenv(key, tunnel.socketPath)
|
|
||||||
if err != nil {
|
|
||||||
return noopCloser{}, fmt.Errorf("override DOCKER_HOST to tunneled socket: %w", err)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return tunnel, nil
|
return TunnelResult{
|
||||||
|
Closer: tunnel,
|
||||||
|
SocketPath: tunnel.socketPath,
|
||||||
|
Created: true,
|
||||||
|
}, nil
|
||||||
}
|
}
|
||||||
return noopCloser{}, nil
|
return TunnelResult{Closer: noopCloser{}}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
type noopCloser struct{}
|
type noopCloser struct{}
|
||||||
|
|
@ -86,7 +91,7 @@ func (t *tunneledDockerHost) Close() error {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *SSHHandler) createDockerHostTunnel(ctx context.Context, remoteHost string) (*tunneledDockerHost, error) {
|
func (self *SSHHandler) createDockerHostTunnel(ctx context.Context, remoteHost string) (*tunneledDockerHost, error) {
|
||||||
socketDir, err := self.tempDir("/tmp", "lazydocker-sshtunnel-")
|
socketDir, err := self.tempDir("/tmp", "lazydocker-ssh-tunnel-")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("create ssh tunnel tmp file: %w", err)
|
return nil, fmt.Errorf("create ssh tunnel tmp file: %w", err)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -51,7 +51,7 @@ func TestSSHHandlerHandleSSHDockerHost(t *testing.T) {
|
||||||
|
|
||||||
tempDir := func(dir string, pattern string) (string, error) {
|
tempDir := func(dir string, pattern string) (string, error) {
|
||||||
assert.Equal(t, "/tmp", dir)
|
assert.Equal(t, "/tmp", dir)
|
||||||
assert.Equal(t, "lazydocker-sshtunnel-", pattern)
|
assert.Equal(t, "lazydocker-ssh-tunnel-", pattern)
|
||||||
|
|
||||||
return "/tmp/lazydocker-ssh-tunnel-12345", nil
|
return "/tmp/lazydocker-ssh-tunnel-12345", nil
|
||||||
}
|
}
|
||||||
|
|
@ -64,7 +64,7 @@ func TestSSHHandlerHandleSSHDockerHost(t *testing.T) {
|
||||||
|
|
||||||
startCmdCount := 0
|
startCmdCount := 0
|
||||||
startCmd := func(cmd *exec.Cmd) error {
|
startCmd := func(cmd *exec.Cmd) error {
|
||||||
assert.EqualValues(t, []string{"ssh", "-L", "/tmp/lazydocker-ssh-tunnel-12345/dockerhost.sock:/var/run/docker.sock", "192.168.5.178", "-N"}, cmd.Args)
|
assert.EqualValues(t, []string{"ssh", "-L", "/tmp/lazydocker-ssh-tunnel-12345/dockerhost.sock:/var/run/docker.sock", s.envVarValue, "-N"}, cmd.Args)
|
||||||
|
|
||||||
startCmdCount++
|
startCmdCount++
|
||||||
|
|
||||||
|
|
@ -91,7 +91,7 @@ func TestSSHHandlerHandleSSHDockerHost(t *testing.T) {
|
||||||
setenv: setenv,
|
setenv: setenv,
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err := handler.HandleSSHDockerHost()
|
_, err := handler.HandleSSHDockerHost(s.envVarValue)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
||||||
assert.Equal(t, s.expectedDialContextCount, dialContextCount)
|
assert.Equal(t, s.expectedDialContextCount, dialContextCount)
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue