Skip to content

Commit

Permalink
Allow running OpenTelemetry collector
Browse files Browse the repository at this point in the history
  • Loading branch information
JamieMagee committed Oct 18, 2023
1 parent 7440eb5 commit ebd7842
Show file tree
Hide file tree
Showing 6 changed files with 183 additions and 43 deletions.
26 changes: 15 additions & 11 deletions cmd/dependabot/internal/cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,17 +12,20 @@ import (
)

var (
file string
cache string
debugging bool
proxyCertPath string
extraHosts []string
output string
pullImages bool
volumes []string
timeout time.Duration
updaterImage string
proxyImage string
file string
cache string
debugging bool
enableOpenTelemetry bool
proxyCertPath string
collectorConfigPath string
extraHosts []string
output string
pullImages bool
volumes []string
timeout time.Duration
updaterImage string
proxyImage string
collectorImage string
)

// rootCmd represents the base command when called without any subcommands
Expand Down Expand Up @@ -50,4 +53,5 @@ func init() {

rootCmd.PersistentFlags().StringVar(&updaterImage, "updater-image", "", "container image to use for the updater")
rootCmd.PersistentFlags().StringVar(&proxyImage, "proxy-image", infra.ProxyImageName, "container image to use for the proxy")
rootCmd.PersistentFlags().StringVar(&collectorImage, "collector-image", infra.CollectorImageName, "container image to use for the OpenTelemetry collector")
}
37 changes: 21 additions & 16 deletions cmd/dependabot/internal/cmd/test.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,22 +37,25 @@ var testCmd = &cobra.Command{
processInput(&scenario.Input)

if err := infra.Run(infra.RunParams{
CacheDir: cache,
Creds: scenario.Input.Credentials,
Debug: debugging,
Expected: scenario.Output,
ExtraHosts: extraHosts,
InputName: file,
InputRaw: inputRaw,
Job: &scenario.Input.Job,
LocalDir: local,
Output: output,
ProxyCertPath: proxyCertPath,
ProxyImage: proxyImage,
PullImages: pullImages,
Timeout: timeout,
UpdaterImage: updaterImage,
Volumes: volumes,
CacheDir: cache,
Creds: scenario.Input.Credentials,
Debug: debugging,
EnableOpenTelemetry: enableOpenTelemetry,
Expected: scenario.Output,
ExtraHosts: extraHosts,
InputName: file,
InputRaw: inputRaw,
Job: &scenario.Input.Job,
LocalDir: local,
Output: output,
ProxyCertPath: proxyCertPath,
ProxyImage: proxyImage,
CollectorConfigPath: collectorConfigPath,
CollectorImage: collectorImage,
PullImages: pullImages,
Timeout: timeout,
UpdaterImage: updaterImage,
Volumes: volumes,
}); err != nil {
log.Fatal(err)
}
Expand Down Expand Up @@ -88,8 +91,10 @@ func init() {
testCmd.Flags().StringVar(&cache, "cache", "", "cache import/export directory")
testCmd.Flags().StringVar(&local, "local", "", "local directory to use as fetched source")
testCmd.Flags().StringVar(&proxyCertPath, "proxy-cert", "", "path to a certificate the proxy will trust")
testCmd.Flags().StringVar(&collectorConfigPath, "collector-config", "", "path to an OpenTelemetry collector config file")
testCmd.Flags().BoolVar(&pullImages, "pull", true, "pull the image if it isn't present")
testCmd.Flags().BoolVar(&debugging, "debug", false, "run an interactive shell inside the updater")
testCmd.Flags().BoolVar(&enableOpenTelemetry, "enable-opentelemetry", false, "enable OpenTelemetry tracing")
testCmd.Flags().StringArrayVarP(&volumes, "volume", "v", nil, "mount volumes in Docker")
testCmd.Flags().StringArrayVar(&extraHosts, "extra-hosts", nil, "Docker extra hosts setting on the proxy")
testCmd.Flags().DurationVarP(&timeout, "timeout", "t", 0, "max time to run an update")
Expand Down
37 changes: 21 additions & 16 deletions cmd/dependabot/internal/cmd/update.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,22 +61,25 @@ func NewUpdateCommand() *cobra.Command {
}

if err := infra.Run(infra.RunParams{
CacheDir: cache,
Creds: input.Credentials,
Debug: debugging,
Expected: nil, // update subcommand doesn't use expectations
ExtraHosts: extraHosts,
InputName: file,
Job: &input.Job,
LocalDir: local,
Output: output,
ProxyCertPath: proxyCertPath,
ProxyImage: proxyImage,
PullImages: pullImages,
Timeout: timeout,
UpdaterImage: updaterImage,
Writer: writer,
Volumes: volumes,
CacheDir: cache,
Creds: input.Credentials,
Debug: debugging,
EnableOpenTelemetry: enableOpenTelemetry,
Expected: nil, // update subcommand doesn't use expectations
ExtraHosts: extraHosts,
InputName: file,
Job: &input.Job,
LocalDir: local,
Output: output,
ProxyCertPath: proxyCertPath,
ProxyImage: proxyImage,
CollectorConfigPath: collectorConfigPath,
CollectorImage: collectorImage,
PullImages: pullImages,
Timeout: timeout,
UpdaterImage: updaterImage,
Writer: writer,
Volumes: volumes,
}); err != nil {
log.Fatalf("failed to run updater: %v", err)
}
Expand All @@ -96,8 +99,10 @@ func NewUpdateCommand() *cobra.Command {
cmd.Flags().StringVar(&cache, "cache", "", "cache import/export directory")
cmd.Flags().StringVar(&local, "local", "", "local directory to use as fetched source")
cmd.Flags().StringVar(&proxyCertPath, "proxy-cert", "", "path to a certificate the proxy will trust")
cmd.Flags().StringVar(&collectorConfigPath, "collector-config", "", "path to an OpenTelemetry collector config file")
cmd.Flags().BoolVar(&pullImages, "pull", true, "pull the image if it isn't present")
cmd.Flags().BoolVar(&debugging, "debug", false, "run an interactive shell inside the updater")
cmd.Flags().BoolVar(&enableOpenTelemetry, "enable-opentelemetry", false, "enable OpenTelemetry tracing")
cmd.Flags().StringArrayVarP(&volumes, "volume", "v", nil, "mount volumes in Docker")
cmd.Flags().StringArrayVar(&extraHosts, "extra-hosts", nil, "Docker extra hosts setting on the proxy")
cmd.Flags().DurationVarP(&timeout, "timeout", "t", 0, "max time to run an update")
Expand Down
99 changes: 99 additions & 0 deletions internal/infra/open_telemetry.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
package infra

import (
"context"
"fmt"
"github.com/docker/docker/api/types"
"github.com/docker/docker/api/types/container"
"github.com/docker/docker/api/types/mount"
"github.com/docker/docker/api/types/network"
"github.com/moby/moby/client"
"os"
"path"
"path/filepath"
)

// CollectorImageName is the default Docker image used
const CollectorImageName = "ghcr.io/open-telemetry/opentelemetry-collector-releases/opentelemetry-collector-contrib:latest"

const CollectorConfigPath = "/etc/otelcol-contrib/config.yaml"

const sslCertificates = "/etc/ssl/certs/ca-certificates.crt"

type Collector struct {
cli *client.Client
containerID string
}

// NewCollector starts the OpenTelemetry collector container.
func NewCollector(ctx context.Context, cli *client.Client, net *Networks, params *RunParams, proxy *Proxy) (*Collector, error) {
hostCfg := &container.HostConfig{
AutoRemove: false,
}

containerCfg := &container.Config{
Image: params.CollectorImage,
Env: []string{
fmt.Sprintf("HTTP_PROXY=%s", proxy.url),
fmt.Sprintf("HTTPS_PROXY=%s", proxy.url),
},
}

netCfg := &network.NetworkingConfig{
EndpointsConfig: map[string]*network.EndpointSettings{
net.noInternetName: {
NetworkID: net.NoInternet.ID,
},
},
}

if params.CollectorConfigPath != "" {
if !filepath.IsAbs(params.CollectorConfigPath) {
// needs to be absolute, assume it is relative to the working directory
var dir string
dir, err := os.Getwd()
if err != nil {
return nil, fmt.Errorf("couldn't get working directory: %w", err)
}
params.CollectorConfigPath = path.Join(dir, params.CollectorConfigPath)
}
hostCfg.Mounts = append(hostCfg.Mounts, mount.Mount{
Type: mount.TypeBind,
Source: params.CollectorConfigPath,
Target: CollectorConfigPath,
ReadOnly: true,
})
}

collectorContainer, err := cli.ContainerCreate(ctx, containerCfg, hostCfg, netCfg, nil, "")
if err != nil {
return nil, fmt.Errorf("failed to create collector container: %w", err)
}

collector := &Collector{
cli: cli,
containerID: collectorContainer.ID,
}

opt := types.CopyToContainerOptions{}
if t, err := tarball(sslCertificates, proxy.ca.Cert); err != nil {
return nil, fmt.Errorf("failed to create cert tarball: %w", err)
} else if err = cli.CopyToContainer(ctx, collector.containerID, "/", t, opt); err != nil {
return nil, fmt.Errorf("failed to copy cert to container: %w", err)
}

if err = cli.ContainerStart(ctx, collectorContainer.ID, types.ContainerStartOptions{}); err != nil {
collector.Close()
return nil, fmt.Errorf("failed to start collector container: %w", err)
}

return collector, nil

}

// Close kills and deletes the container and deletes updater mount paths related to the run.
func (u *Collector) Close() error {
return u.cli.ContainerRemove(context.Background(), u.containerID, types.ContainerRemoveOptions{
Force: true,
})
}
22 changes: 22 additions & 0 deletions internal/infra/run.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,8 @@ type RunParams struct {
PullImages bool
// run an interactive shell?
Debug bool
// EnableOpenTelemetry enables OpenTelemetry tracing
EnableOpenTelemetry bool
// Volumes are used to mount directories in Docker
Volumes []string
// Timeout specifies an optional maximum duration the CLI will run an update.
Expand All @@ -57,6 +59,10 @@ type RunParams struct {
UpdaterImage string
// ProxyImage is the image to use for the proxy
ProxyImage string
// CollectorImage is the image to use for the OpenTelemetry collector
CollectorImage string
// CollectorConfigPath is the path to the OpenTelemetry collector configuration file
CollectorConfigPath string
// Writer is where API calls will be written to
Writer io.Writer
InputName string
Expand Down Expand Up @@ -256,6 +262,9 @@ func setImageNames(params *RunParams) error {
if params.ProxyImage == "" {
params.ProxyImage = ProxyImageName
}
if params.CollectorImage == "" {
params.CollectorImage = CollectorImageName
}
if params.UpdaterImage == "" {
pm, ok := packageManagerLookup[params.Job.PackageManager]
if !ok {
Expand Down Expand Up @@ -326,6 +335,11 @@ func runContainers(ctx context.Context, params RunParams, api *server.API) error
return err
}

err = pullImage(ctx, cli, params.CollectorImage)
if err != nil {
return err
}

err = pullImage(ctx, cli, params.UpdaterImage)
if err != nil {
return err
Expand All @@ -349,6 +363,14 @@ func runContainers(ctx context.Context, params RunParams, api *server.API) error
go prox.TailLogs(ctx, cli)
}

if params.EnableOpenTelemetry {
collector, err := NewCollector(ctx, cli, networks, &params, prox)
if err != nil {
return err
}
defer collector.Close()
}

updater, err := NewUpdater(ctx, cli, networks, &params, prox)
if err != nil {
return err
Expand Down
5 changes: 5 additions & 0 deletions internal/infra/updater.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,11 @@ func NewUpdater(ctx context.Context, cli *client.Client, net *Networks, params *
Cmd: []string{"/bin/sh"},
Tty: true, // prevent container from stopping
}

if params.EnableOpenTelemetry == true {
containerCfg.Env = append(containerCfg.Env, "OTEL_ENABLED=true")
}

hostCfg := &container.HostConfig{}
var err error
for _, v := range params.Volumes {
Expand Down

0 comments on commit ebd7842

Please sign in to comment.