From 32b649ac0fc3f6f6de6000ef9de6acac1c7f919a Mon Sep 17 00:00:00 2001 From: Moritz Clasmeier Date: Fri, 10 Apr 2026 13:36:49 +0200 Subject: [PATCH 1/2] Check specifically if running in *roxie* Container, not just somehow containerized --- Dockerfile | 1 + cmd/deploy.go | 4 +--- cmd/env.go | 8 ++++---- cmd/subshell.go | 2 +- go.mod | 1 - go.sum | 2 -- internal/containerutil/detect.go | 19 ++++++------------- internal/containerutil/detect_test.go | 10 +++++----- internal/env/env.go | 16 ++++++++-------- 9 files changed, 26 insertions(+), 37 deletions(-) diff --git a/Dockerfile b/Dockerfile index a295b277..44afd507 100644 --- a/Dockerfile +++ b/Dockerfile @@ -207,6 +207,7 @@ USER roxie # Set environment variables ENV HOME=/ \ + RUNNING_IN_ROXIE_CONTAINER=true \ KUBECONFIG=/kubeconfig \ PATH=/usr/local/bin:$PATH diff --git a/cmd/deploy.go b/cmd/deploy.go index 2c2daf9c..05719f3a 100644 --- a/cmd/deploy.go +++ b/cmd/deploy.go @@ -99,7 +99,7 @@ func runDeploy(cmd *cobra.Command, args []string) error { portForwardEnabledFinal := portForwarding || exposure == "none" - if env.RunningInContainer { + if env.RunningInRoxieContainer { // For running containerized we have specific requirements. if portForwardEnabledFinal { return errors.New("containerized mode does not support port-forwarding") @@ -117,8 +117,6 @@ func runDeploy(cmd *cobra.Command, args []string) error { return fmt.Errorf("containerized mode requires /kubeconfig file: %w", err) } } - log.Dim("Using KUBECONFIG=/kubeconfig.") - os.Setenv("KUBECONFIG", "/kubeconfig") } if konflux { diff --git a/cmd/env.go b/cmd/env.go index 5e19ea65..6ad05bba 100644 --- a/cmd/env.go +++ b/cmd/env.go @@ -29,10 +29,10 @@ func runEnv(cmd *cobra.Command, args []string) error { fmt.Println("Roxie Environment Information:") fmt.Println("==============================") - fmt.Printf("Kube config: %s\n", os.Getenv("KUBECONFIG")) - fmt.Printf("Running in Container: %v\n", env.RunningInContainer) - fmt.Printf("Current Context: %s\n", env.GetCurrentContext()) - fmt.Printf("Cluster Type: %s\n", env.GetCurrentClusterType().String()) + fmt.Printf("Kube config: %s\n", os.Getenv("KUBECONFIG")) + fmt.Printf("Running in roxie container: %v\n", env.RunningInRoxieContainer) + fmt.Printf("Current Context: %s\n", env.GetCurrentContext()) + fmt.Printf("Cluster Type: %s\n", env.GetCurrentClusterType().String()) return nil } diff --git a/cmd/subshell.go b/cmd/subshell.go index 5a1c97d1..4a9b5c1b 100644 --- a/cmd/subshell.go +++ b/cmd/subshell.go @@ -182,7 +182,7 @@ func printBanner(endpoint, exposure string, haproxyAvailable, haproxyStarted boo cyan.Println("[roxie] Central UI: http://localhost:8080 (username: admin, password: see $ROX_ADMIN_PASSWORD)") } else if exposure != "none" && exposure != "" { cyan.Printf("[roxie] Central UI: https://%s", endpoint) - } else if !env.RunningInContainer { + } else if !env.RunningInRoxieContainer { cyan.Println("[roxie] Note: Installing haproxy enables automatic HTTP access to Central at http://localhost:8080") } diff --git a/go.mod b/go.mod index 732f4dd3..b631a556 100644 --- a/go.mod +++ b/go.mod @@ -4,7 +4,6 @@ go 1.25.0 require ( github.com/fatih/color v1.16.0 - github.com/moby/sys/mountinfo v0.7.2 github.com/spf13/cobra v1.8.0 golang.org/x/term v0.38.0 gopkg.in/yaml.v3 v3.0.1 diff --git a/go.sum b/go.sum index 3c7a2d32..f06dd208 100644 --- a/go.sum +++ b/go.sum @@ -20,8 +20,6 @@ github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovk github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= -github.com/moby/sys/mountinfo v0.7.2 h1:1shs6aH5s4o5H2zQLn796ADW1wMrIwHsyJ2v9KouLrg= -github.com/moby/sys/mountinfo v0.7.2/go.mod h1:1YOa8w8Ih7uW0wALDUgT1dTTSBrZ+HiBLGws92L2RU4= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= diff --git a/internal/containerutil/detect.go b/internal/containerutil/detect.go index 8146f054..b54ac8a2 100644 --- a/internal/containerutil/detect.go +++ b/internal/containerutil/detect.go @@ -1,19 +1,12 @@ package containerutil import ( - "github.com/moby/sys/mountinfo" + "os" ) -// IsRunningInContainer detects if the current process is running inside -// a Docker, Podman, or Kubernetes container by checking if the root -// filesystem is an overlay filesystem (standard for containers). -func IsRunningInContainer() bool { - // Get root mount info using efficient filter - rootMounts, err := mountinfo.GetMounts(mountinfo.SingleEntryFilter("/")) - if err != nil || len(rootMounts) == 0 { - return false - } - - // Containers use overlay filesystem for root - return rootMounts[0].FSType == "overlay" +// IsRunningInRoxieContainer checks if we are running inside the released roxie container. +// This knowledge allows us to adjust behavior accordingly, allowing for some UX improvements. +func IsRunningInRoxieContainer() bool { + _, exists := os.LookupEnv("RUNNING_IN_ROXIE_CONTAINER") + return exists } diff --git a/internal/containerutil/detect_test.go b/internal/containerutil/detect_test.go index 8af142d6..665f0549 100644 --- a/internal/containerutil/detect_test.go +++ b/internal/containerutil/detect_test.go @@ -4,20 +4,20 @@ import ( "testing" ) -func TestIsRunningInContainer(t *testing.T) { +func TestIsRunningInRoxieContainer(t *testing.T) { // This test simply verifies the function doesn't panic // The actual result depends on whether the test is running // inside a container or not - result := IsRunningInContainer() + result := IsRunningInRoxieContainer() // Log the result for informational purposes - t.Logf("IsRunningInContainer() = %v", result) + t.Logf("IsRunningInRoxieContainer() = %v", result) // We can't assert a specific value since it depends on the environment // But we can verify it returns a boolean without errors if result { - t.Log("Detected running inside a container") + t.Log("Detected running inside a roxie container") } else { - t.Log("Detected running on host (not in container)") + t.Log("Running outside of roxie container") } } diff --git a/internal/env/env.go b/internal/env/env.go index dd816939..843d02e3 100644 --- a/internal/env/env.go +++ b/internal/env/env.go @@ -18,9 +18,9 @@ import ( ) var ( - RunningInContainer bool - RunningInteractively bool - initializationMutex sync.Mutex + RunningInRoxieContainer bool + RunningInteractively bool + initializationMutex sync.Mutex ) // ClusterType represents different types of Kubernetes clusters @@ -51,8 +51,8 @@ var ( ) func init() { - RunningInContainer = containerutil.IsRunningInContainer() - if RunningInContainer { + RunningInRoxieContainer = containerutil.IsRunningInRoxieContainer() + if RunningInRoxieContainer { os.Setenv("KUBECONFIG", "/kubeconfig") } RunningInteractively = isRunningInteractively() @@ -143,7 +143,7 @@ func Initialize(log *logger.Logger) error { if log == nil { log = logger.New() } - if RunningInContainer { + if RunningInRoxieContainer { log.Dim("Running containerized.") } @@ -284,11 +284,11 @@ func kubeconfigChecks(log *logger.Logger) error { if err != nil { log.Warningf("Kubeconfig %s cannot be opened for reading.", kubeConfigPath) if errors.Is(err, os.ErrNotExist) { - if RunningInContainer { + if RunningInRoxieContainer { log.Warningf("Make sure that your kubeconfig is mounted into the container, as in: -v $KUBECONFIG:/kubeconfig:U") } } else { - if RunningInContainer { + if RunningInRoxieContainer { log.Warningf("Make sure that your kubeconfig is mounted with the 'U' option, as in: -v $KUBECONFIG:/kubeconfig:U") } } From fdbd286ba3e1d5e623e249c0a9f9cff7c39d71f0 Mon Sep 17 00:00:00 2001 From: Moritz Clasmeier Date: Sun, 12 Apr 2026 21:53:23 +0200 Subject: [PATCH 2/2] Updated detection logic and test --- go.mod | 3 +++ internal/containerutil/detect.go | 14 ++++++++++++-- internal/containerutil/detect_test.go | 21 ++++++++------------- 3 files changed, 23 insertions(+), 15 deletions(-) diff --git a/go.mod b/go.mod index b631a556..8f3b9390 100644 --- a/go.mod +++ b/go.mod @@ -11,6 +11,7 @@ require ( ) require ( + github.com/davecgh/go-spew v1.1.1 // indirect github.com/fxamacker/cbor/v2 v2.9.0 // indirect github.com/go-logr/logr v1.4.3 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect @@ -19,7 +20,9 @@ require ( github.com/mattn/go-isatty v0.0.20 // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/reflect2 v1.0.3-0.20250322232337-35a7c28c31ee // indirect + github.com/pmezard/go-difflib v1.0.0 // indirect github.com/spf13/pflag v1.0.9 // indirect + github.com/stretchr/testify v1.11.1 // indirect github.com/x448/float16 v0.8.4 // indirect go.yaml.in/yaml/v2 v2.4.3 // indirect golang.org/x/net v0.48.0 // indirect diff --git a/internal/containerutil/detect.go b/internal/containerutil/detect.go index b54ac8a2..9a4ea8f5 100644 --- a/internal/containerutil/detect.go +++ b/internal/containerutil/detect.go @@ -1,12 +1,22 @@ package containerutil import ( + "fmt" "os" + "strconv" ) // IsRunningInRoxieContainer checks if we are running inside the released roxie container. // This knowledge allows us to adjust behavior accordingly, allowing for some UX improvements. func IsRunningInRoxieContainer() bool { - _, exists := os.LookupEnv("RUNNING_IN_ROXIE_CONTAINER") - return exists + strVal, exists := os.LookupEnv("RUNNING_IN_ROXIE_CONTAINER") + if !exists || strVal == "" { + return false + } + val, err := strconv.ParseBool(strVal) + if err != nil { + fmt.Fprintf(os.Stderr, "Warning: Invalid value for RUNNING_IN_ROXIE_CONTAINER: %s. Expected a boolean value (true/false). Defaulting to false.\n", strVal) + return false + } + return val } diff --git a/internal/containerutil/detect_test.go b/internal/containerutil/detect_test.go index 665f0549..e7e1658c 100644 --- a/internal/containerutil/detect_test.go +++ b/internal/containerutil/detect_test.go @@ -2,22 +2,17 @@ package containerutil import ( "testing" + + "github.com/stretchr/testify/assert" ) func TestIsRunningInRoxieContainer(t *testing.T) { - // This test simply verifies the function doesn't panic - // The actual result depends on whether the test is running - // inside a container or not - result := IsRunningInRoxieContainer() + t.Setenv("RUNNING_IN_ROXIE_CONTAINER", "true") + assert.True(t, IsRunningInRoxieContainer(), "Expected to detect running in roxie container when environment variable is set") - // Log the result for informational purposes - t.Logf("IsRunningInRoxieContainer() = %v", result) + t.Setenv("RUNNING_IN_ROXIE_CONTAINER", "") + assert.False(t, IsRunningInRoxieContainer(), "Expected to not detect running in roxie container when environment variable is unset") - // We can't assert a specific value since it depends on the environment - // But we can verify it returns a boolean without errors - if result { - t.Log("Detected running inside a roxie container") - } else { - t.Log("Running outside of roxie container") - } + t.Setenv("RUNNING_IN_ROXIE_CONTAINER", "garbage") + assert.False(t, IsRunningInRoxieContainer(), "Expected to not detect running in roxie container when environment variable has invalid value") }