@@ -2,13 +2,16 @@ package env
22
33import (
44 "encoding/json"
5+ "errors"
56 "fmt"
67 "net/url"
78 "os"
89 "os/exec"
10+ "path/filepath"
911 "strings"
1012
1113 "github.com/stackrox/roxie/internal/containerutil"
14+ "github.com/stackrox/roxie/internal/logger"
1215 "golang.org/x/term"
1316)
1417
@@ -65,25 +68,33 @@ func isRunningInteractively() bool {
6568
6669// ensureInitialized performs lazy initialization of cluster information
6770// This avoids contacting the cluster on package import
68- func ensureInitialized () {
71+ func ensureInitialized (log * logger. Logger ) error {
6972 if ! initialized {
70- kubeConfig := fetchKubeConfig ()
73+ if RunningInContainer {
74+ log .Dim ("Running containerized." )
75+ }
76+ kubeConfig , err := fetchKubeConfig (log )
77+ if err != nil {
78+ return err
79+ }
7180 currentContext = kubeConfig .CurrentContext
72- apiResources := fetchAPIResources ()
81+ apiResources , err := fetchAPIResources ()
82+ if err != nil {
83+ return err
84+ }
7385 currentClusterType = detectClusterType (kubeConfig , apiResources )
7486 initialized = true
7587 }
88+ return nil
7689}
7790
7891// GetCurrentClusterType returns the current cluster type, initializing if needed
7992func GetCurrentClusterType () ClusterType {
80- ensureInitialized ()
8193 return currentClusterType
8294}
8395
8496// GetCurrentContext returns the current kubectl context, initializing if needed
8597func GetCurrentContext () string {
86- ensureInitialized ()
8798 return currentContext
8899}
89100
@@ -113,13 +124,15 @@ type KubeCluster struct {
113124 Server string
114125}
115126
116- // DetectClusterType identifies the cluster type for the current kubectl context
117- // This is a convenience wrapper that fetches the kubeconfig and API resources,
118- // then delegates to detectClusterType for the actual detection logic
119- func DetectClusterType () ClusterType {
120- kubeConfig := fetchKubeConfig ()
121- apiResources := fetchAPIResources ()
122- return detectClusterType (kubeConfig , apiResources )
127+ // Initialize performs environment initialization and sets the global variables.
128+ func Initialize (log * logger.Logger ) error {
129+ if log == nil {
130+ log = logger .New ()
131+ }
132+ if err := ensureInitialized (log ); err != nil {
133+ return fmt .Errorf ("failed to initialize environment: %w" , err )
134+ }
135+ return nil
123136}
124137
125138// detectClusterType implements the cluster type detection logic
@@ -180,20 +193,23 @@ func isOpenShift4(apiResources []string) bool {
180193}
181194
182195// fetchKubeConfig retrieves the current kubectl configuration
183- func fetchKubeConfig () KubeConfig {
196+ func fetchKubeConfig (log * logger.Logger ) (KubeConfig , error ) {
197+ if err := kubeconfigChecks (log ); err != nil {
198+ return KubeConfig {}, err
199+ }
184200 // Get current context
185201 cmd := exec .Command ("kubectl" , "config" , "current-context" )
186202 output , err := cmd .Output ()
187203 if err != nil {
188- return KubeConfig {}
204+ return KubeConfig {}, errors . New ( "failed to get current context" )
189205 }
190206 currentContext := strings .TrimSpace (string (output ))
191207
192208 // Get cluster info
193209 cmd = exec .Command ("kubectl" , "config" , "view" , "--minify" , "-o" , "json" )
194210 output , err = cmd .Output ()
195211 if err != nil {
196- return KubeConfig {CurrentContext : currentContext }
212+ return KubeConfig {}, fmt . Errorf ( "failed to obtain minified kubeconfig: %w" , err )
197213 }
198214
199215 var rawConfig struct {
@@ -207,7 +223,7 @@ func fetchKubeConfig() KubeConfig {
207223 }
208224
209225 if err := json .Unmarshal (output , & rawConfig ); err != nil {
210- return KubeConfig {CurrentContext : currentContext }
226+ return KubeConfig {}, fmt . Errorf ( "failed to unmarshal kubeconfig: %w" , err )
211227 }
212228
213229 clusters := make ([]KubeCluster , len (rawConfig .Clusters ))
@@ -221,19 +237,57 @@ func fetchKubeConfig() KubeConfig {
221237 return KubeConfig {
222238 CurrentContext : currentContext ,
223239 Clusters : clusters ,
240+ }, nil
241+ }
242+
243+ func kubeconfigChecks (log * logger.Logger ) error {
244+ kubeConfigPath , err := getKubeConfigPath ()
245+ if err != nil {
246+ return fmt .Errorf ("getting kubeconfig path: %w" , err )
247+ }
248+ log .Infof ("Using kubeconfig %s" , kubeConfigPath )
249+ if _ , err := os .Stat (kubeConfigPath ); err != nil {
250+ log .Warningf ("Kubeconfig %s cannot be found." , kubeConfigPath )
251+ if RunningInContainer {
252+ log .Warningf ("Make sure that your kubeconfig is mounted into the container, as in: -v $KUBECONFIG:/kubeconfig:U" )
253+ }
254+ return fmt .Errorf ("failed to stat kubeconfig %s: %w" , kubeConfigPath , err )
255+ }
256+
257+ file , err := os .Open (kubeConfigPath )
258+ if err != nil {
259+ log .Warningf ("Kubeconfig %s cannot be opened for reading." , kubeConfigPath )
260+ if RunningInContainer {
261+ log .Warningf ("Make sure that your kubeconfig is mounted with the 'U' option, as in: -v $KUBECONFIG:/kubeconfig:U" )
262+ }
263+ return fmt .Errorf ("failed to open kubeconfig %s: %w" , kubeConfigPath , err )
264+ }
265+ _ = file .Close ()
266+ return nil
267+ }
268+
269+ func getKubeConfigPath () (string , error ) {
270+ kubeConfigPath := os .Getenv ("KUBECONFIG" )
271+ if kubeConfigPath == "" {
272+ home := os .Getenv ("HOME" )
273+ if home == "" {
274+ return "" , errors .New ("HOME environment variable is not set" )
275+ }
276+ kubeConfigPath = filepath .Join (home , ".kube" , "config" )
224277 }
278+ return kubeConfigPath , nil
225279}
226280
227281// fetchAPIResources retrieves the list of API resources from the cluster
228- func fetchAPIResources () []string {
282+ func fetchAPIResources () ( []string , error ) {
229283 cmd := exec .Command ("kubectl" , "api-resources" , "-o" , "name" )
230284 output , err := cmd .Output ()
231285 if err != nil {
232- return nil
286+ return nil , fmt . Errorf ( "failed to retrieve API resources: %w" , err )
233287 }
234288
235289 lines := strings .Split (strings .TrimSpace (string (output )), "\n " )
236- return lines
290+ return lines , nil
237291}
238292
239293func IsInStackroxRepository () bool {
0 commit comments