Skip to content

Commit 5cea39d

Browse files
authored
Merge pull request #30 from asteurer/podman
feat: add podman support
2 parents d8771b2 + 350f2a0 commit 5cea39d

File tree

5 files changed

+61
-28
lines changed

5 files changed

+61
-28
lines changed

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ Spin applications have the ability to export metrics and trace data. This plugin
1010

1111
This plugin relies on third-party software to work properly. Please be sure you have the following installed before continuing:
1212

13-
- Latest version of [Docker](https://www.docker.com/products/docker-desktop)
13+
- Latest version of [Docker](https://www.docker.com/products/docker-desktop) or [Podman](https://podman.io/docs)
1414

1515
# Installation
1616

@@ -49,7 +49,7 @@ The `otel` plugin currently supports two different observability stacks:
4949

5050
- Default: Multi-container observability stack based on Prometheus, Loki, Grafana and Jaeger
5151
- Aspire: Single-container observability stack using .NET Aspire Dashboard
52-
52+
5353
# Usage
5454

5555
Once the plugin is installed, you can try the below commands:

cmd/cleanup.go

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -26,12 +26,12 @@ func init() {
2626
cleanUpCmd.Flags().BoolVarP(&removeContainers, "remove", "r", false, "If specified, OTel containers will be removed")
2727
}
2828

29-
func getIDs(dockerOutput []byte) []string {
29+
func getIDs(runtimeOutput []byte) []string {
3030
var result []string
31-
outputArray := strings.Split(string(dockerOutput), "\n")
31+
outputArray := strings.Split(string(runtimeOutput), "\n")
3232

3333
// skip the first line of the output, because it is the table header row
34-
// docker ps does not support hiding column headers
34+
// {{runtime}} ps does not support hiding column headers
3535
for _, entry := range outputArray[1:] {
3636
fields := strings.Fields(entry)
3737
if len(fields) > 0 {
@@ -43,21 +43,22 @@ func getIDs(dockerOutput []byte) []string {
4343
}
4444

4545
func cleanUp() error {
46-
if err := checkDocker(); err != nil {
46+
runtime, err := detectContainerRuntime()
47+
if err != nil {
4748
return err
4849
}
4950

50-
fmt.Println("Stopping Spin OpenTelemetry Docker containers...")
51-
getContainers := exec.Command("docker", "ps", fmt.Sprintf("--filter=name=%s*", otelConfigDirName), "--format=table")
52-
dockerPsOutput, err := getContainers.CombinedOutput()
51+
fmt.Println("Stopping Spin OpenTelemetry containers...")
52+
getContainers := exec.Command(runtime, "ps", fmt.Sprintf("--filter=name=%s*", otelConfigDirName))
53+
processOutput, err := getContainers.CombinedOutput()
5354
if err != nil {
54-
fmt.Println(string(dockerPsOutput))
55+
fmt.Println(string(processOutput))
5556
return err
5657
}
5758

58-
containerIDs := getIDs(dockerPsOutput)
59+
containerIDs := getIDs(processOutput)
5960

60-
// The `docker stop` command will throw an error if there are no containers to stop
61+
// The `{{runtime}} stop` command will throw an error if there are no containers to stop
6162
if len(containerIDs) == 0 {
6263
fmt.Println("No Spin OpenTelemetry resources found. Nothing to clean up.")
6364
return nil
@@ -67,7 +68,7 @@ func cleanUp() error {
6768
if removeContainers {
6869
cleanupArgs = []string{"rm", "-f"}
6970
}
70-
stopContainers := exec.Command("docker", append(cleanupArgs, containerIDs...)...)
71+
stopContainers := exec.Command(runtime, append(cleanupArgs, containerIDs...)...)
7172
stopContainersOutput, err := stopContainers.CombinedOutput()
7273
if err != nil {
7374
fmt.Println(string(stopContainersOutput))

cmd/root.go

Lines changed: 41 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import (
55
"os"
66
"os/exec"
77
"path"
8+
"strings"
89

910
open "github.com/fermyon/otel-plugin/cmd/open"
1011
"github.com/spf13/cobra"
@@ -35,19 +36,51 @@ func setOtelConfigPath() error {
3536
return nil
3637
}
3738

38-
// checkDocker checks whether Docker is installed and the Docker daemon is running
39-
func checkDocker() error {
40-
cmd := exec.Command("docker", "--version")
41-
if err := cmd.Run(); err != nil {
42-
return fmt.Errorf("Docker appears not to be installed, so please visit their install page and try again once installed: https://www.docker.com/products/docker-desktop")
39+
// detectContainerRuntime checks for a supported container runtime.
40+
//
41+
// Returns the detected runtime name.
42+
func detectContainerRuntime() (string, error) {
43+
// Default Docker, fallback Podman
44+
runtimesToCheck := []string{"docker", "podman"}
45+
runtime := ""
46+
for _, rt := range runtimesToCheck {
47+
cmd := exec.Command(rt, "--version")
48+
if err := cmd.Run(); err != nil {
49+
continue
50+
}
51+
runtime = rt
52+
break
53+
}
54+
55+
if runtime == "" {
56+
return "", fmt.Errorf("Unable to detect container runtime.\nPlease ensure at least one of the following is installed and in the PATH: %s\n", strings.Join(runtimesToCheck, ", "))
57+
}
58+
59+
if runtime == "podman" {
60+
// Podman doesn't auto-install a compose provider
61+
composeProvidersToCheck := []string{"podman-compose", "docker-compose"}
62+
composeProvider := ""
63+
for _, rt := range composeProvidersToCheck {
64+
cmd := exec.Command(rt, "--version")
65+
if err := cmd.Run(); err != nil {
66+
continue
67+
}
68+
69+
composeProvider = rt
70+
break
71+
}
72+
73+
if composeProvider == "" {
74+
return "", fmt.Errorf("Unable to detect compose provider.\n Please ensure at least one of the following is installed and in the PATH: %s\n", strings.Join(composeProvidersToCheck, ", "))
75+
}
4376
}
4477

45-
cmd = exec.Command("docker", "info")
78+
cmd := exec.Command(runtime, "info")
4679
if err := cmd.Run(); err != nil {
47-
return fmt.Errorf("The Docker daemon appears not to be running. The command to start Docker depends on your operating system. For instructions, check the correct page under https://docs.docker.com/engine/install")
80+
return "", fmt.Errorf("The daemon/virtual machine for %[1]s appears not to be running. Please check the documentation for %[1]s for more information.", runtime)
4881
}
4982

50-
return nil
83+
return runtime, nil
5184
}
5285

5386
func Execute() {

cmd/setup.go

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,8 @@ var (
1414
aspire = false
1515
setUpCmd = &cobra.Command{
1616
Use: "setup",
17-
Short: "Run OpenTelemetry dependencies in Docker.",
17+
Short: "Run OpenTelemetry dependencies as containers",
18+
Long: "Required OpenTelemetry dependencies will be started as containers using a supported container runtime (docker, podman)",
1819
RunE: func(cmd *cobra.Command, args []string) error {
1920
s := stack.GetStackByFlags(aspire)
2021
if err := setUp(s); err != nil {
@@ -30,16 +31,18 @@ func init() {
3031
}
3132

3233
func setUp(s stack.Stack) error {
33-
if err := checkDocker(); err != nil {
34+
runtime, err := detectContainerRuntime()
35+
if err != nil {
3436
return err
3537
}
38+
3639
composeFileName := s.GetComposeFileName()
3740
composeFilePath := path.Join(otelConfigPath, composeFileName)
3841
if _, err := os.Stat(composeFilePath); os.IsNotExist(err) {
3942
return fmt.Errorf("The \"otel-config\" directory is missing the \"%s\" file, so please consider removing and re-installing the otel plugin", composeFileName)
4043
}
4144

42-
cmd := exec.Command("docker", "compose", "-f", composeFilePath, "up", "-d")
45+
cmd := exec.Command(runtime, "compose", "-f", composeFilePath, "up", "-d")
4346

4447
fmt.Println("Pulling and running Spin OpenTelemetry resources...")
4548

cmd/up.go

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,10 +22,6 @@ var upCmd = &cobra.Command{
2222
}
2323

2424
func up(args []string) error {
25-
if err := checkDocker(); err != nil {
26-
return err
27-
}
28-
2925
pathToSpin := os.Getenv("SPIN_BIN_PATH")
3026
if pathToSpin == "" {
3127
return fmt.Errorf("Please ensure that you are running \"spin otel up\", rather than calling the OpenTelemetry plugin binary directly")

0 commit comments

Comments
 (0)