mirror of https://github.com/hashicorp/consul
173 lines
4.7 KiB
Go
173 lines
4.7 KiB
Go
// Copyright (c) HashiCorp, Inc.
|
|
// SPDX-License-Identifier: BUSL-1.1
|
|
|
|
package build
|
|
|
|
import (
|
|
"context"
|
|
"strings"
|
|
|
|
"github.com/hashicorp/go-hclog"
|
|
|
|
"github.com/hashicorp/consul/testing/deployer/sprawl/internal/runner"
|
|
"github.com/hashicorp/consul/testing/deployer/topology"
|
|
)
|
|
|
|
const dockerfileEnvoy = `
|
|
ARG CONSUL_IMAGE
|
|
ARG ENVOY_IMAGE
|
|
FROM ${CONSUL_IMAGE}
|
|
FROM ${ENVOY_IMAGE}
|
|
COPY --from=0 /bin/consul /bin/consul
|
|
`
|
|
|
|
// FROM hashicorp/consul-dataplane:latest
|
|
// COPY --from=busybox:uclibc /bin/sh /bin/sh
|
|
// TODO: busybox:latest doesn't work, see https://hashicorp.slack.com/archives/C03EUN3QF1C/p1691784078972959
|
|
const dockerfileDataplane = `
|
|
ARG DATAPLANE_IMAGE
|
|
FROM busybox:1.34
|
|
FROM ${DATAPLANE_IMAGE}
|
|
COPY --from=0 /bin/busybox /bin/busybox
|
|
USER 0:0
|
|
RUN ["busybox", "--install", "/bin", "-s"]
|
|
USER 100:0
|
|
ENTRYPOINT []
|
|
`
|
|
|
|
const dockerfileDataplaneForTProxy = `
|
|
ARG DATAPLANE_IMAGE
|
|
ARG CONSUL_IMAGE
|
|
FROM ${CONSUL_IMAGE} AS consul
|
|
FROM ${DATAPLANE_IMAGE} AS distroless
|
|
FROM debian:bullseye-slim
|
|
|
|
# undo the distroless aspect
|
|
COPY --from=distroless /usr/local/bin/discover /usr/local/bin/
|
|
COPY --from=distroless /usr/local/bin/envoy /usr/local/bin/
|
|
COPY --from=distroless /usr/local/bin/consul-dataplane /usr/local/bin/
|
|
COPY --from=distroless /licenses/copyright.txt /licenses/
|
|
|
|
COPY --from=consul /bin/consul /bin/
|
|
|
|
# Install iptables and sudo, needed for tproxy.
|
|
RUN apt update -y \
|
|
&& apt install -y iptables sudo curl dnsutils
|
|
|
|
RUN sed '/_apt/d' /etc/passwd > /etc/passwd.new \
|
|
&& mv -f /etc/passwd.new /etc/passwd \
|
|
&& adduser --uid=100 consul --no-create-home --disabled-password --system \
|
|
&& adduser consul sudo \
|
|
&& echo 'consul ALL=(ALL) NOPASSWD:ALL' >> /etc/sudoers
|
|
|
|
COPY <<'EOF' /bin/tproxy-startup.sh
|
|
#!/bin/sh
|
|
|
|
set -ex
|
|
|
|
# HACK: UID of consul in the consul-client container
|
|
# This is conveniently also the UID of apt in the envoy container
|
|
CONSUL_UID=100
|
|
ENVOY_UID=$(id -u)
|
|
|
|
# - We allow 19000 so that the test can directly visit the envoy admin page.
|
|
# - We allow 20000 so that envoy can receive mTLS traffic from other nodes.
|
|
# - We (reluctantly) allow 8080 so that we can bypass envoy and talk to fortio
|
|
# to do test assertions.
|
|
sudo consul connect redirect-traffic \
|
|
-proxy-uid $ENVOY_UID \
|
|
-exclude-uid $CONSUL_UID \
|
|
-proxy-inbound-port=15001 \
|
|
-exclude-inbound-port=19000 \
|
|
-exclude-inbound-port=20000 \
|
|
-exclude-inbound-port=8080
|
|
exec "$@"
|
|
EOF
|
|
|
|
RUN chmod +x /bin/tproxy-startup.sh \
|
|
&& chown 100:0 /bin/tproxy-startup.sh
|
|
|
|
RUN echo 'consul ALL=(ALL) NOPASSWD:ALL' >> /etc/sudoers
|
|
|
|
USER 100:0
|
|
ENTRYPOINT []
|
|
`
|
|
|
|
func DockerImages(
|
|
logger hclog.Logger,
|
|
run *runner.Runner,
|
|
t *topology.Topology,
|
|
) error {
|
|
|
|
built := make(map[string]struct{})
|
|
for _, c := range t.Clusters {
|
|
for _, n := range c.Nodes {
|
|
needsTproxy := n.NeedsTransparentProxy()
|
|
|
|
joint := n.Images.EnvoyConsulImage()
|
|
if _, ok := built[joint]; joint != "" && !ok {
|
|
logger.Info("building envoy+consul image", "image", joint)
|
|
logw := logger.Named("docker_envoy_consul").StandardWriter(&hclog.StandardLoggerOptions{ForceLevel: hclog.Debug})
|
|
|
|
err := run.DockerExecWithStderr(context.TODO(), []string{
|
|
"build",
|
|
// provenance causes non-idempotent builds, which leads to spurious terraform replacements
|
|
"--provenance=false",
|
|
"--build-arg",
|
|
"CONSUL_IMAGE=" + n.Images.Consul,
|
|
"--build-arg",
|
|
"ENVOY_IMAGE=" + n.Images.Envoy,
|
|
"-t", joint,
|
|
"-",
|
|
}, logw, logw, strings.NewReader(dockerfileEnvoy))
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
built[joint] = struct{}{}
|
|
}
|
|
|
|
cdp := n.Images.LocalDataplaneImage()
|
|
if _, ok := built[cdp]; cdp != "" && !ok {
|
|
logger.Info("building dataplane image", "image", cdp)
|
|
logw := logger.Named("docker_dataplane").StandardWriter(&hclog.StandardLoggerOptions{ForceLevel: hclog.Debug})
|
|
err := run.DockerExecWithStderr(context.TODO(), []string{
|
|
"build",
|
|
"--provenance=false",
|
|
"--build-arg",
|
|
"DATAPLANE_IMAGE=" + n.Images.Dataplane,
|
|
"-t", cdp,
|
|
"-",
|
|
}, logw, logw, strings.NewReader(dockerfileDataplane))
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
built[cdp] = struct{}{}
|
|
}
|
|
|
|
cdpTproxy := n.Images.LocalDataplaneTProxyImage()
|
|
if _, ok := built[cdpTproxy]; cdpTproxy != "" && !ok && needsTproxy {
|
|
logger.Info("building image", "image", cdpTproxy)
|
|
logw := logger.Named("docker_dataplane_tproxy").StandardWriter(&hclog.StandardLoggerOptions{ForceLevel: hclog.Debug})
|
|
err := run.DockerExecWithStderr(context.TODO(), []string{
|
|
"build",
|
|
"--build-arg",
|
|
"DATAPLANE_IMAGE=" + n.Images.Dataplane,
|
|
"--build-arg",
|
|
"CONSUL_IMAGE=" + n.Images.Consul,
|
|
"-t", cdpTproxy,
|
|
"-",
|
|
}, logw, logw, strings.NewReader(dockerfileDataplaneForTProxy))
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
built[cdpTproxy] = struct{}{}
|
|
}
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}
|