Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow running OpenTelemetry collector #181

Merged
merged 5 commits into from
Oct 23, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 14 additions & 11 deletions cmd/dependabot/internal/cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,17 +12,19 @@ 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
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 +52,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")
}
35 changes: 19 additions & 16 deletions cmd/dependabot/internal/cmd/test.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,22 +37,24 @@ 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,
CollectorConfigPath: collectorConfigPath,
CollectorImage: collectorImage,
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,
}); err != nil {
log.Fatal(err)
}
Expand Down Expand Up @@ -88,6 +90,7 @@ 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")
JamieMagee marked this conversation as resolved.
Show resolved Hide resolved
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().StringArrayVarP(&volumes, "volume", "v", nil, "mount volumes in Docker")
Expand Down
35 changes: 19 additions & 16 deletions cmd/dependabot/internal/cmd/update.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,22 +61,24 @@ 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,
CollectorConfigPath: collectorConfigPath,
CollectorImage: collectorImage,
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,
Volumes: volumes,
Writer: writer,
}); err != nil {
log.Fatalf("failed to run updater: %v", err)
}
Expand All @@ -96,6 +98,7 @@ 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")
JamieMagee marked this conversation as resolved.
Show resolved Hide resolved
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().StringArrayVarP(&volumes, "volume", "v", nil, "mount volumes in Docker")
Expand Down
104 changes: 104 additions & 0 deletions internal/infra/open_telemetry.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
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),
JamieMagee marked this conversation as resolved.
Show resolved Hide resolved
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 stops and removes the container.
func (c *Collector) Close() error {
timeout := 5
_ = c.cli.ContainerStop(context.Background(), c.containerID, container.StopOptions{Timeout: &timeout})

err := c.cli.ContainerRemove(context.Background(), c.containerID, types.ContainerRemoveOptions{Force: true})
if err != nil {
return fmt.Errorf("failed to remove collector container: %w", err)
}
return nil
}
22 changes: 22 additions & 0 deletions internal/infra/run.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,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 +260,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 +333,13 @@ func runContainers(ctx context.Context, params RunParams, api *server.API) error
return err
}

if params.CollectorConfigPath != "" {
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.CollectorConfigPath != "" {
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.CollectorConfigPath != "" {
containerCfg.Env = append(containerCfg.Env, "OTEL_ENABLED=true")
}

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