Skip to content

Commit

Permalink
feat(docker): support copy ssh key
Browse files Browse the repository at this point in the history
  • Loading branch information
CarlJi committed Sep 11, 2024
1 parent 0589958 commit a13741e
Show file tree
Hide file tree
Showing 5 changed files with 68 additions and 6 deletions.
2 changes: 1 addition & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ COPY deploy/github-known-hosts /github_known_hosts

# set go proxy and private repo
RUN go env -w GOPROXY=https://goproxy.cn,direct \
&& go env -w GOPRIVATE=github.com/qbox
&& go env -w GOPRIVATE=github.com/qbox,qiniu.com

EXPOSE 8888

Expand Down
2 changes: 1 addition & 1 deletion config/.image/golangci-lint.1.59.1.Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,6 @@ COPY deploy/github-known-hosts /github_known_hosts

# set go proxy and private repo
RUN go env -w GOPROXY=https://goproxy.cn,direct \
&& go env -w GOPRIVATE=github.com/qbox
&& go env -w GOPRIVATE=github.com/qbox,qiniu.com

EXPOSE 8888
27 changes: 26 additions & 1 deletion config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,11 +36,26 @@ type GlobalConfig struct {
// if not empty, use the config to run javastylecheck-lint.
// it can be overridden by linter.ConfigPath.
JavaStyleCheckRuleConfig string `json:"javastylecheckruleConfig,omitempty"`

// CopySSHKeyToContainer is the path of the ssh key file to copy to the container.
// optional, if not empty, copy the ssh key to the container.
// it only works when using the docker runner.
// format can be:
// 1. /path/to/ssh/key => will copy the key to the same path(/path/to/ssh/key) in the container
// 2. /path/to/ssh/key:/another/path/to/ssh/key => will copy the key to the target path(/another/path/to/ssh/key) in the container
// it can be overridden by linter.DockerAsRunner.CopySSHKeyToContainer.
CopySSHKeyToContainer string `json:"copySSHKeyToContainer,omitempty"`
}

type DockerAsRunner struct {
Image string `json:"image"`
CopyLinterFromOrigin bool `json:"copylinterFromOrigin,omitempty"`
CopyLinterFromOrigin bool `json:"copyLinterFromOrigin,omitempty"`
// CopySSHKeyToContainer is the path of the ssh key file to copy to the container.
// optional, if not empty, copy the ssh key to the container.
// format can be:
// 1. /path/to/ssh/key => will copy the key to the same path(/path/to/ssh/key) in the container
// 2. /path/to/ssh/key:/another/path/to/ssh/key => will copy the key to the target path(/another/path/to/ssh/key) in the container
CopySSHKeyToContainer string `json:"copySSHKeyToContainer,omitempty"`
}
type Linter struct {
// Name is the linter name.
Expand Down Expand Up @@ -125,6 +140,8 @@ func NewConfig(conf string) (Config, error) {
}
}

// TODO(CarlJi): do we need to check the format of the copy ssh key here?

return c, nil
}

Expand All @@ -149,6 +166,11 @@ func (c Config) Get(org, repo, ln string) Linter {
linter.ConfigPath = c.GlobalDefaultConfig.JavaStyleCheckRuleConfig
}

// set copy ssh key to container
if c.GlobalDefaultConfig.CopySSHKeyToContainer != "" {
linter.DockerAsRunner.CopySSHKeyToContainer = c.GlobalDefaultConfig.CopySSHKeyToContainer
}

if orgConfig, ok := c.CustomConfig[org]; ok {
if l, ok := orgConfig[ln]; ok {
linter = applyCustomConfig(linter, l)
Expand Down Expand Up @@ -199,6 +221,9 @@ func applyCustomConfig(legacy, custom Linter) Linter {
if custom.DockerAsRunner.CopyLinterFromOrigin {
legacy.DockerAsRunner.CopyLinterFromOrigin = custom.DockerAsRunner.CopyLinterFromOrigin
}
if custom.DockerAsRunner.CopySSHKeyToContainer != "" {
legacy.DockerAsRunner.CopySSHKeyToContainer = custom.DockerAsRunner.CopySSHKeyToContainer
}

if custom.Name != "" {
legacy.Name = custom.Name
Expand Down
42 changes: 39 additions & 3 deletions internal/runner/docker.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ import (
"io"
"os"
"os/exec"
"path/filepath"
"sort"
"strings"

Expand Down Expand Up @@ -130,7 +129,8 @@ func (d *DockerRunner) Run(ctx context.Context, cfg *config.Linter) (io.ReadClos

// NOTE(Carl): do not know why mount volume does not work in DinD mode,
// copy the code to container instead.
if err := d.copyToContainer(ctx, resp.ID, cfg.WorkDir, filepath.Dir(cfg.WorkDir)); err != nil {
log.Infof("copy code to container: src: %s, dst: %s", cfg.WorkDir, cfg.WorkDir)
if err := d.copyToContainer(ctx, resp.ID, cfg.WorkDir, cfg.WorkDir); err != nil {
return nil, fmt.Errorf("failed to copy code to container: %w", err)
}

Expand All @@ -140,12 +140,31 @@ func (d *DockerRunner) Run(ctx context.Context, cfg *config.Linter) (io.ReadClos
return nil, fmt.Errorf("failed to find %s :%w", cfg.Name, err)
}

log.Infof("copy linter to container: src: %s, dst: %s", linterOriginPath, "/usr/local/bin/")
err = d.copyToContainer(ctx, resp.ID, linterOriginPath, "/usr/local/bin/")
if err != nil {
return nil, fmt.Errorf("failed to copy linter to container: %w", err)
}
}

if cfg.DockerAsRunner.CopySSHKeyToContainer != "" {
paths := strings.Split(cfg.DockerAsRunner.CopySSHKeyToContainer, ":")
var srcPath, dstPath string
if len(paths) == 2 {
srcPath, dstPath = paths[0], paths[1]
} else if len(paths) == 1 {
srcPath, dstPath = paths[0], paths[0]
} else {
return nil, fmt.Errorf("invalid copy ssh key format: %s", cfg.DockerAsRunner.CopySSHKeyToContainer)
}

log.Infof("copy ssh key to container: src: %s, dst: %s", srcPath, dstPath)
err = d.copyToContainer(ctx, resp.ID, srcPath, dstPath)
if err != nil {
return nil, fmt.Errorf("failed to copy ssh key to container: %w", err)
}
}

if err := d.cli.ContainerStart(ctx, resp.ID, container.StartOptions{}); err != nil {
return nil, fmt.Errorf("failed to start container: %w", err)
}
Expand Down Expand Up @@ -210,7 +229,11 @@ func (d *DockerRunner) readLogFromContainer(ctx context.Context, containerID str
return cleanReader, nil
}

// mainly refer https://github.com/docker/cli/blob/b1d27091e50595fecd8a2a4429557b70681395b2/cli/command/container/cp.go#L186
func (d *DockerRunner) copyToContainer(ctx context.Context, containerID, srcPath, dstPath string) error {
// Prepare destination copy info by stat-ing the container path.
dstInfo := archive.CopyInfo{Path: dstPath}

// prepare source code dir
srcInfo, err := archive.CopyInfoSourcePath(srcPath, false)
if err != nil {
Expand All @@ -223,7 +246,20 @@ func (d *DockerRunner) copyToContainer(ctx context.Context, containerID, srcPath
}
defer srcArchive.Close()

err = d.cli.CopyToContainer(ctx, containerID, dstPath, srcArchive, container.CopyToContainerOptions{})
var (
resolvedDstPath string
content io.ReadCloser
)
dstDir, preparedArchive, err := archive.PrepareArchiveCopy(srcArchive, srcInfo, dstInfo)
if err != nil {
return err
}
defer preparedArchive.Close()

resolvedDstPath = dstDir
content = preparedArchive

err = d.cli.CopyToContainer(ctx, containerID, resolvedDstPath, content, container.CopyToContainerOptions{})
if err != nil {
return fmt.Errorf("failed to copy to container: %w", err)
}
Expand Down
1 change: 1 addition & 0 deletions internal/runner/runner.go
Original file line number Diff line number Diff line change
Expand Up @@ -138,4 +138,5 @@ type DockerClientInterface interface {
CopyToContainer(ctx context.Context, containerID, dstPath string, content io.Reader, options container.CopyToContainerOptions) error
ContainerWait(ctx context.Context, containerID string, condition container.WaitCondition) (<-chan container.WaitResponse, <-chan error)
CopyFromContainer(ctx context.Context, containerID, srcPath string) (io.ReadCloser, container.PathStat, error)
ContainerStatPath(ctx context.Context, containerID, path string) (container.PathStat, error)
}

0 comments on commit a13741e

Please sign in to comment.