feat: add a route to the traefik dashboard

This commit is contained in:
Dan Anglin 2021-07-11 19:39:39 +01:00
parent 2a761272a0
commit 5e21bf67e8
Signed by: dananglin
GPG key ID: 0C1D44CFBEE68638
9 changed files with 106 additions and 22 deletions

View file

@ -20,7 +20,6 @@ type DockerConfig struct {
} }
// DockerNetworkConfig contains configuration for creating the docker network. // DockerNetworkConfig contains configuration for creating the docker network.
type DockerNetworkConfig struct { type DockerNetworkConfig struct {
Name string `json:"name"` Name string `json:"name"`
Subnet string `json:"subnet"` Subnet string `json:"subnet"`
@ -41,10 +40,12 @@ type ServicesConfig struct {
// TraefikConfig contains configuration for the Traefik container. // TraefikConfig contains configuration for the Traefik container.
type TraefikConfig struct { type TraefikConfig struct {
CheckNewVersion bool `json:"checkNewVersion"` CheckNewVersion bool `json:"checkNewVersion"`
ContainerIp string `json:"containerIp"`
Domain string `json:"domain"`
GroupId int
LogLevel string `json:"logLevel"`
SendAnonymousUsage bool `json:"sendAnonymousUsage"` SendAnonymousUsage bool `json:"sendAnonymousUsage"`
Version string `json:"version"` Version string `json:"version"`
ContainerIp string `json:"containerIp"`
LogLevel string `json:"logLevel"`
} }
// NewConfig creates a new Config value from a given // NewConfig creates a new Config value from a given

View file

@ -30,10 +30,11 @@ func TestValidConfig(t *testing.T) {
Services: ServicesConfig{ Services: ServicesConfig{
Traefik: TraefikConfig{ Traefik: TraefikConfig{
CheckNewVersion: true, CheckNewVersion: true,
ContainerIp: "172.17.1.2",
Domain: "forge.localhost",
LogLevel: "info",
SendAnonymousUsage: false, SendAnonymousUsage: false,
Version: "v2.4.9", Version: "v2.4.9",
ContainerIp: "172.17.1.2",
LogLevel: "info",
}, },
}, },
}, },

View file

@ -16,7 +16,8 @@
"sendAnonymousUsage": false, "sendAnonymousUsage": false,
"version": "v2.4.9", "version": "v2.4.9",
"containerIp": "172.17.1.2", "containerIp": "172.17.1.2",
"logLevel": "info" "logLevel": "info",
"domain": "forge.localhost"
} }
} }
} }

View file

@ -10,23 +10,32 @@ import (
// DockerContainerInput is the configuration // DockerContainerInput is the configuration
// used to create the Gitea docker container. // used to create the Gitea docker container.
type DockerContainerInput struct { type DockerContainerInput struct {
Image pulumi.StringInput Image pulumi.StringInput
Ipv4Address pulumi.StringInput Ipv4Address pulumi.StringInput
EnvVars pulumi.StringArray EnvVars pulumi.StringArray
Name pulumi.StringInput Name pulumi.StringInput
Network pulumi.StringInput Network pulumi.StringInput
Volumes []DockerVolumeMount HostPathVolumes []HostPathVolume
UniqueLabel string DockerVolumes []DockerVolume
UniqueLabel string
} }
// DockerVolumeMount is the configuration // HostPathVolume is the configuration
// used for mounting a host directory // used for mounting a host directory
// to a directory inside a container. // to a directory inside a container.
type DockerVolumeMount struct { type HostPathVolume struct {
HostPath pulumi.StringInput HostPath pulumi.StringInput
MountPath pulumi.StringInput MountPath pulumi.StringInput
} }
// DockerVolume is the configuration
// used for mounting a docker volume
// to a directory inside a container.
type DockerVolume struct {
Name pulumi.StringInput
MountPath pulumi.StringInput
}
func CreateContainer(ctx *pulumi.Context, c DockerContainerInput) error { func CreateContainer(ctx *pulumi.Context, c DockerContainerInput) error {
// all containers will mount the host's timezone and localtime files // all containers will mount the host's timezone and localtime files
// to ensure the correct time is synced. // to ensure the correct time is synced.
@ -43,13 +52,21 @@ func CreateContainer(ctx *pulumi.Context, c DockerContainerInput) error {
}, },
} }
// optionally create additional container volumes. // create additional container volumes if specified.
for _, v := range c.Volumes { for _, v := range c.HostPathVolumes {
vArg := docker.ContainerVolumeArgs{ arg := docker.ContainerVolumeArgs{
ContainerPath: v.MountPath, ContainerPath: v.MountPath,
HostPath: v.HostPath, HostPath: v.HostPath,
} }
volumes = append(volumes, vArg) volumes = append(volumes, arg)
}
for _, v := range c.DockerVolumes {
arg := docker.ContainerVolumeArgs{
ContainerPath: v.MountPath,
VolumeName: v.Name,
}
volumes = append(volumes, arg)
} }
args := docker.ContainerArgs{ args := docker.ContainerArgs{

View file

@ -29,6 +29,12 @@ var templateTraefikDockerfile string
//go:embed templates/traefik/traefik.yaml.tmpl //go:embed templates/traefik/traefik.yaml.tmpl
var templateTraefikStaticConfig string var templateTraefikStaticConfig string
//go:embed templates/traefik/dynamic_dashboard.yaml.tmpl
var templateTraefikDynamicDashboardConfig string
//go:embed templates/traefik/entrypoint.sh.tmpl
var templateTraefikEntrypoint string
// newContainerStack creates the ContainerStack value. // newContainerStack creates the ContainerStack value.
func newDockerStack(ctx context.Context, project, stack string, c config.Config) (*DockerStack, error) { func newDockerStack(ctx context.Context, project, stack string, c config.Config) (*DockerStack, error) {
deployFunc := deployDockerStack(project, c.Docker, c.Services) deployFunc := deployDockerStack(project, c.Docker, c.Services)
@ -79,6 +85,9 @@ func (c *DockerStack) Destroy(ctx context.Context) error {
// deployDockerStack returns a Pulumi run function // deployDockerStack returns a Pulumi run function
// that is used to deploy the docker stack. // that is used to deploy the docker stack.
func deployDockerStack(project string, dockerConfig config.DockerConfig, services config.ServicesConfig) pulumi.RunFunc { func deployDockerStack(project string, dockerConfig config.DockerConfig, services config.ServicesConfig) pulumi.RunFunc {
groupID := 2239
services.Traefik.GroupId = groupID
return func(ctx *pulumi.Context) error { return func(ctx *pulumi.Context) error {
// TODO: Create the provider when we start playing with remote hosts // TODO: Create the provider when we start playing with remote hosts
@ -96,11 +105,11 @@ func deployDockerStack(project string, dockerConfig config.DockerConfig, service
// Create the shared volume // Create the shared volume
sharedVolumeInput := docker.DockerVolumeInput{ sharedVolumeInput := docker.DockerVolumeInput{
Name: pulumi.String(dockerConfig.SharedVolume.Name), Name: pulumi.String(dockerConfig.SharedVolume.Name),
UniqueLabel: "shared", UniqueLabel: "shared",
} }
_, err = docker.CreateVolume(ctx, sharedVolumeInput) sharedVolume, err := docker.CreateVolume(ctx, sharedVolumeInput)
if err != nil { if err != nil {
return err return err
} }
@ -125,6 +134,14 @@ func deployDockerStack(project string, dockerConfig config.DockerConfig, service
return fmt.Errorf("unable to generate the Traefik static configuration from template...\n%w", err) return fmt.Errorf("unable to generate the Traefik static configuration from template...\n%w", err)
} }
if err := generateFile(services.Traefik, templateTraefikDynamicDashboardConfig, "traefikDashboardConf", filepath.Join(traefikContextDir, "dynamic_dashboard.yaml")); err != nil {
return fmt.Errorf("unable to generate the Traefik dashboard configuration from template...\n%w", err)
}
if err := generateFile(services.Traefik, templateTraefikEntrypoint, "traefikEntrypoint", filepath.Join(traefikContextDir, "entrypoint.sh")); err != nil {
return fmt.Errorf("unable to generate the Traefik entrypoint script from template...\n%w", err)
}
c := docker.DockerImageInput{ c := docker.DockerImageInput{
BuildContext: pulumi.String(traefikContextDir), BuildContext: pulumi.String(traefikContextDir),
Dockerfile: pulumi.String(filepath.Join(traefikContextDir, "Dockerfile")), Dockerfile: pulumi.String(filepath.Join(traefikContextDir, "Dockerfile")),
@ -144,6 +161,12 @@ func deployDockerStack(project string, dockerConfig config.DockerConfig, service
Name: pulumi.String("helix-traefik"), Name: pulumi.String("helix-traefik"),
Network: network.Name, Network: network.Name,
UniqueLabel: "traefik-container", UniqueLabel: "traefik-container",
DockerVolumes: []docker.DockerVolume{
{
Name: sharedVolume.Name,
MountPath: pulumi.String("/helix/shared"),
},
},
} }
if err = docker.CreateContainer(ctx, traefikContainerInput); err != nil { if err = docker.CreateContainer(ctx, traefikContainerInput); err != nil {

View file

@ -2,6 +2,12 @@ FROM traefik:{{ .Version }}
ADD traefik.yml /helix/traefik/ ADD traefik.yml /helix/traefik/
ADD entrypoint.sh /
ADD dynamic_dashboard.yaml /tmp/
RUN chmod +x /entrypoint.sh
EXPOSE 22 80 443 EXPOSE 22 80 443
CMD ["--configfile=/helix/traefik/traefik.yml"] CMD ["--configfile=/helix/traefik/traefik.yml"]

View file

@ -0,0 +1,9 @@
---
http:
routers:
dashboard:
entryPoints:
- "https"
rule: "Host(`{{ .Domain }}`) && (PathPrefix(`/api`) || PathPrefix(`/dashboard`))"
service: "api@internal"
tls: {}

View file

@ -0,0 +1,26 @@
#!/bin/sh
set -e
# Create the dynamic config directory in the shared volume.
mkdir -p /helix/shared/traefik/dynamic
chgrp {{ .GroupId }} /helix/shared/traefik/dynamic
chmod a-rwx,u+rwx,g+rwx /helix/shared/traefik/dynamic
# Move the dashboard config to the new directory.
mv /tmp/dynamic_dashboard.yaml /helix/shared/traefik/dynamic/dashboard.yaml
# first arg is `-f` or `--some-option`
if [ "${1#-}" != "$1" ]; then
set -- traefik "$@"
fi
# if our command is a valid Traefik subcommand, let's invoke it through Traefik instead
# (this allows for "docker run traefik version", etc)
if traefik "$1" --help >/dev/null 2>&1
then
set -- traefik "$@"
else
echo "= '$1' is not a Traefik command: assuming shell execution." 1>&2
fi
exec "$@"

View file

@ -22,6 +22,6 @@ entryPoints:
providers: providers:
file: file:
watch: true watch: true
directory: "/helix/traefik/config/dynamic" directory: "/helix/shared/traefik/dynamic"
log: log:
level: "{{ .LogLevel }}" level: "{{ .LogLevel }}"