source tmate binary from docker image

This commit is contained in:
Brad Rydzewski
2020-11-11 17:24:24 -05:00
parent bb9e46aab0
commit 2457d8d0d7
11 changed files with 127 additions and 26 deletions

View File

@@ -37,6 +37,7 @@ type compileCommand struct {
Labels map[string]string Labels map[string]string
Secrets map[string]string Secrets map[string]string
Resources compiler.Resources Resources compiler.Resources
Tmate compiler.Tmate
Clone bool Clone bool
Config string Config string
} }
@@ -101,6 +102,7 @@ func (c *compileCommand) run(*kingpin.ParseContext) error {
Environ: provider.Static(c.Environ), Environ: provider.Static(c.Environ),
Labels: c.Labels, Labels: c.Labels,
Resources: c.Resources, Resources: c.Resources,
Tmate: c.Tmate,
Privileged: append(c.Privileged, compiler.Privileged...), Privileged: append(c.Privileged, compiler.Privileged...),
Networks: c.Networks, Networks: c.Networks,
Volumes: c.Volumes, Volumes: c.Volumes,
@@ -192,6 +194,13 @@ func registerCompile(app *kingpin.Application) {
cmd.Flag("docker-config", "path to the docker config file"). cmd.Flag("docker-config", "path to the docker config file").
StringVar(&c.Config) StringVar(&c.Config)
cmd.Flag("tmate-image", "tmate docker image").
Default("drone/drone-runner-docker:latest").
StringVar(&c.Tmate.Image)
cmd.Flag("tmate-enabled", "tmate enabled").
BoolVar(&c.Tmate.Enabled)
// shared pipeline flags // shared pipeline flags
c.Flags = internal.ParseFlags(cmd) c.Flags = internal.ParseFlags(cmd)
} }

View File

@@ -106,6 +106,11 @@ type Config struct {
Config string `envconfig:"DRONE_DOCKER_CONFIG"` Config string `envconfig:"DRONE_DOCKER_CONFIG"`
Stream bool `envconfig:"DRONE_DOCKER_STREAM_PULL" default:"true"` Stream bool `envconfig:"DRONE_DOCKER_STREAM_PULL" default:"true"`
} }
Tmate struct {
Enabled bool `envconfig:"DRONE_TMATE_ENABLED" default:"true"`
Image string `envconfig:"DRONE_TMATE_IMAGE" default:"drone/drone-runner-docker:latest"`
}
} }
// legacy environment variables. the key is the legacy // legacy environment variables. the key is the legacy

View File

@@ -141,6 +141,10 @@ func (c *daemonCommand) run(*kingpin.ParseContext) error {
CPUSet: config.Resources.CPUSet, CPUSet: config.Resources.CPUSet,
ShmSize: config.Resources.ShmSize, ShmSize: config.Resources.ShmSize,
}, },
Tmate: compiler.Tmate{
Image: config.Tmate.Image,
Enabled: config.Tmate.Enabled,
},
Environ: provider.Combine( Environ: provider.Combine(
provider.Static(config.Runner.Environ), provider.Static(config.Runner.Environ),
provider.External( provider.External(

View File

@@ -49,6 +49,7 @@ type execCommand struct {
Labels map[string]string Labels map[string]string
Secrets map[string]string Secrets map[string]string
Resources compiler.Resources Resources compiler.Resources
Tmate compiler.Tmate
Clone bool Clone bool
Config string Config string
Pretty bool Pretty bool
@@ -120,6 +121,7 @@ func (c *execCommand) run(*kingpin.ParseContext) error {
Environ: provider.Static(c.Environ), Environ: provider.Static(c.Environ),
Labels: c.Labels, Labels: c.Labels,
Resources: c.Resources, Resources: c.Resources,
Tmate: c.Tmate,
Privileged: append(c.Privileged, compiler.Privileged...), Privileged: append(c.Privileged, compiler.Privileged...),
Networks: c.Networks, Networks: c.Networks,
Volumes: c.Volumes, Volumes: c.Volumes,
@@ -327,6 +329,13 @@ func registerExec(app *kingpin.Application) {
cmd.Flag("docker-config", "path to the docker config file"). cmd.Flag("docker-config", "path to the docker config file").
StringVar(&c.Config) StringVar(&c.Config)
cmd.Flag("tmate-image", "tmate docker image").
Default("drone/drone-runner-docker:latest").
StringVar(&c.Tmate.Image)
cmd.Flag("tmate-enabled", "tmate enabled").
BoolVar(&c.Tmate.Enabled)
cmd.Flag("debug", "enable debug logging"). cmd.Flag("debug", "enable debug logging").
BoolVar(&c.Debug) BoolVar(&c.Debug)

View File

@@ -1,7 +1,12 @@
FROM alpine:3.6 as alpine FROM alpine:3 as alpine
RUN apk add -U --no-cache ca-certificates RUN apk add -U --no-cache ca-certificates
FROM alpine:3.6 RUN wget https://github.com/tmate-io/tmate/releases/download/2.4.0/tmate-2.4.0-static-linux-amd64.tar.xz
RUN tar -xf tmate-2.4.0-static-linux-amd64.tar.xz
RUN mv tmate-2.4.0-static-linux-amd64/tmate /bin/
RUN chmod +x /bin/tmate
FROM alpine:3
EXPOSE 3000 EXPOSE 3000
ENV GODEBUG netdns=go ENV GODEBUG netdns=go
@@ -9,6 +14,7 @@ ENV DRONE_PLATFORM_OS linux
ENV DRONE_PLATFORM_ARCH amd64 ENV DRONE_PLATFORM_ARCH amd64
COPY --from=alpine /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/ COPY --from=alpine /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/
COPY --from=alpine /bin/tmate /bin
LABEL com.centurylinklabs.watchtower.stop-signal="SIGINT" LABEL com.centurylinklabs.watchtower.stop-signal="SIGINT"

View File

@@ -1,7 +1,12 @@
FROM alpine:3.6 as alpine FROM alpine:3 as alpine
RUN apk add -U --no-cache ca-certificates RUN apk add -U --no-cache ca-certificates
FROM alpine:3.6 RUN wget https://github.com/tmate-io/tmate/releases/download/2.4.0/tmate-2.4.0-static-linux-arm32v7.tar.xz
RUN tar -xf tmate-2.4.0-static-linux-arm32v7.tar.xz
RUN mv tmate-2.4.0-static-linux-arm32v7/tmate /bin/
RUN chmod +x /bin/tmate
FROM alpine:3
EXPOSE 3000 EXPOSE 3000
ENV GODEBUG netdns=go ENV GODEBUG netdns=go

View File

@@ -1,7 +1,12 @@
FROM alpine:3.6 as alpine FROM alpine:3 as alpine
RUN apk add -U --no-cache ca-certificates RUN apk add -U --no-cache ca-certificates
FROM alpine:3.6 RUN wget https://github.com/tmate-io/tmate/releases/download/2.4.0/tmate-2.4.0-static-linux-arm64v8.tar.xz
RUN tar -xf tmate-2.4.0-static-linux-arm64v8.tar.xz
RUN mv tmate-2.4.0-static-linux-arm64v8/tmate /bin/
RUN chmod +x /bin/tmate
FROM alpine:3
EXPOSE 3000 EXPOSE 3000
ENV GODEBUG netdns=go ENV GODEBUG netdns=go

View File

@@ -53,6 +53,12 @@ type Resources struct {
ShmSize int64 ShmSize int64
} }
// Tmate defines tmate settings.
type Tmate struct {
Image string
Enabled bool
}
// Compiler compiles the Yaml configuration file to an // Compiler compiles the Yaml configuration file to an
// intermediate representation optimized for simple execution. // intermediate representation optimized for simple execution.
type Compiler struct { type Compiler struct {
@@ -92,6 +98,10 @@ type Compiler struct {
// applies to pipeline containers. // applies to pipeline containers.
Resources Resources Resources Resources
// Tate provides global configration options for tmate
// live debugging.
Tmate Tmate
// Secret returns a named secret value that can be injected // Secret returns a named secret value that can be injected
// into the pipeline step. // into the pipeline step.
Secret secret.Provider Secret secret.Provider
@@ -307,6 +317,38 @@ func (c *Compiler) Compile(ctx context.Context, args runtime.CompilerArgs) runti
} }
} }
// create internal steps if build running in debug mode
if c.Tmate.Enabled && args.Build.Debug && pipeline.Platform.OS != "windows" {
// first we need to add an internal setup step to the pipeline
// to copy over the tmate binary. Internal steps are not visible
// to the end user.
spec.Internal = append(spec.Internal, &engine.Step{
ID: random(),
Labels: labels,
Pull: engine.PullIfNotExists,
Image: image.Expand(c.Tmate.Image),
Entrypoint: []string{"/bin/sh", "-c"},
Command: []string{"cp /bin/tmate /usr/drone/bin/"},
Network: "none",
})
// next we create a temporary volume to share the tmate binary
// with the pipeline containers.
for _, step := range append(spec.Steps, spec.Internal...) {
step.Volumes = append(step.Volumes, &engine.VolumeMount{
Name: "_addons",
Path: "/usr/drone/bin",
})
}
spec.Volumes = append(spec.Volumes, &engine.Volume{
EmptyDir: &engine.VolumeEmptyDir{
ID: random(),
Name: "_addons",
Labels: labels,
},
})
}
if isGraph(spec) == false { if isGraph(spec) == false {
configureSerial(spec) configureSerial(spec)
} else if pipeline.Clone.Disable == false { } else if pipeline.Clone.Disable == false {
@@ -345,7 +387,7 @@ func (c *Compiler) Compile(ctx context.Context, args runtime.CompilerArgs) runti
} }
} }
for _, step := range spec.Steps { for _, step := range append(spec.Steps, spec.Internal...) {
STEPS: STEPS:
for _, cred := range creds { for _, cred := range creds {
if image.MatchHostname(step.Image, cred.Address) { if image.MatchHostname(step.Image, cred.Address) {

View File

@@ -58,23 +58,8 @@ echo + %s
const tmateScript = ` const tmateScript = `
remote_debug() { remote_debug() {
if [ "$?" -ne "0" ]; if [ "$?" -ne "0" ]; then
then /usr/drone/bin/tmate -F
if command -v apt-get &> /dev/null
then
apt-get update -qq
apt-get install xz-utils --assume-yes -qq
fi
wget https://github.com/tmate-io/tmate/releases/download/2.4.0/tmate-2.4.0-static-linux-amd64.tar.xz
tar -xf tmate-2.4.0-static-linux-amd64.tar.xz
mv tmate-2.4.0-static-linux-amd64/tmate /usr/bin/
chmod +x /usr/bin/tmate
rm -rf tmate-2.4.0-static-linux-amd64
rm -rf tmate-2.4.0-static-linux-amd64.tar.xz
tmate -F
fi fi
} }

View File

@@ -8,6 +8,7 @@ import (
"context" "context"
"io" "io"
"io/ioutil" "io/ioutil"
"time"
"github.com/drone-runners/drone-runner-docker/internal/docker/errors" "github.com/drone-runners/drone-runner-docker/internal/docker/errors"
"github.com/drone-runners/drone-runner-docker/internal/docker/image" "github.com/drone-runners/drone-runner-docker/internal/docker/image"
@@ -90,6 +91,35 @@ func (e *Docker) Setup(ctx context.Context, specv runtime.Spec) error {
Labels: spec.Network.Labels, Labels: spec.Network.Labels,
}) })
// launches the inernal setup steps
for _, step := range spec.Internal {
if err := e.create(ctx, spec, step, ioutil.Discard); err != nil {
logger.FromContext(ctx).
WithError(err).
WithField("container", step.ID).
Errorln("cannot create tmate container")
return err
}
if err := e.start(ctx, step.ID); err != nil {
logger.FromContext(ctx).
WithError(err).
WithField("container", step.ID).
Errorln("cannot start tmate container")
return err
}
if !step.Detach {
// the internal containers perform short-lived tasks
// and should not require > 1 minute to execute.
//
// just to be on the safe side we apply a timeout to
// ensure we never block pipeline execution because we
// are waiting on an internal task.
ctx, cancel := context.WithTimeout(ctx, time.Minute)
defer cancel()
e.wait(ctx, step.ID)
}
}
return errors.TrimExtraInfo(err) return errors.TrimExtraInfo(err)
} }
@@ -104,12 +134,12 @@ func (e *Docker) Destroy(ctx context.Context, specv runtime.Spec) error {
} }
// stop all containers // stop all containers
for _, step := range spec.Steps { for _, step := range append(spec.Steps, spec.Internal...) {
e.client.ContainerKill(ctx, step.ID, "9") e.client.ContainerKill(ctx, step.ID, "9")
} }
// cleanup all containers // cleanup all containers
for _, step := range spec.Steps { for _, step := range append(spec.Steps, spec.Internal...) {
e.client.ContainerRemove(ctx, step.ID, removeOpts) e.client.ContainerRemove(ctx, step.ID, removeOpts)
} }

View File

@@ -17,6 +17,7 @@ type (
Spec struct { Spec struct {
Platform Platform `json:"platform,omitempty"` Platform Platform `json:"platform,omitempty"`
Steps []*Step `json:"steps,omitempty"` Steps []*Step `json:"steps,omitempty"`
Internal []*Step `json:"internal,omitempty"`
Volumes []*Volume `json:"volumes,omitempty"` Volumes []*Volume `json:"volumes,omitempty"`
Network Network `json:"network"` Network Network `json:"network"`
} }