@@ -48,10 +48,8 @@ type App struct {
4848 rootCAs * x509.CertPool
4949 clusterDomain string
5050 fileUploadJobTracker * services.FileUploadJobTracker
51- // Used only when MockK8sClient is enabled
52- testEnvState * k8smocks.TestEnvState
53- // Used only when MockMLflowClient is enabled and MLflow is started as a child process
54- mlflowState * mlflowmocks.MLflowState
51+ // cleanupFuncs holds shutdown callbacks for mock processes (envtest, MLflow, LlamaStack)
52+ cleanupFuncs []func ()
5553}
5654
5755func NewApp (cfg config.EnvConfig , logger * slog.Logger ) (* App , error ) {
@@ -100,6 +98,9 @@ func NewApp(cfg config.EnvConfig, logger *slog.Logger) (*App, error) {
10098 }
10199 logger .Info ("Detected dashboard namespace" , "namespace" , dashboardNamespace )
102100
101+ // Track cleanup functions for mock processes
102+ var cleanupFuncs []func ()
103+
103104 // Initialize LlamaStack client factory - clients will be created per request
104105 var llamaStackClientFactory llamastack.LlamaStackClientFactory
105106 if cfg .MockLSClient {
@@ -127,12 +128,11 @@ func NewApp(cfg config.EnvConfig, logger *slog.Logger) (*App, error) {
127128 }
128129
129130 var k8sFactory k8s.KubernetesClientFactory
130- var testEnvState * k8smocks.TestEnvState
131131 if cfg .MockK8sClient {
132132 logger .Info ("Using mocked Kubernetes client" )
133133 var ctrlClient client.Client
134134 ctx , cancel := context .WithCancel (context .Background ())
135- testEnvState , ctrlClient , err = k8smocks .SetupEnvTest (k8smocks.TestEnvInput {
135+ testEnvState , ctrlClient , err : = k8smocks .SetupEnvTest (k8smocks.TestEnvInput {
136136 Users : k8smocks .DefaultTestUsers ,
137137 Logger : logger ,
138138 Ctx : ctx ,
@@ -145,6 +145,13 @@ func NewApp(cfg config.EnvConfig, logger *slog.Logger) (*App, error) {
145145 cancel ()
146146 return nil , fmt .Errorf ("failed to setup envtest: %w" , err )
147147 }
148+ cleanupFuncs = append (cleanupFuncs , func () {
149+ logger .Info ("stopping test environment..." )
150+ k8smocks .CleanupTestEnvState (testEnvState ,
151+ func (format string , args ... any ) { logger .Error (fmt .Sprintf (format , args ... )) },
152+ func (format string , args ... any ) { logger .Info (fmt .Sprintf (format , args ... )) },
153+ )
154+ })
148155 k8sFactory , err = k8smocks .NewMockedKubernetesClientFactory (ctrlClient , testEnvState , cfg , logger )
149156 if err != nil {
150157 // Clean up partially initialized test environment
@@ -176,11 +183,18 @@ func NewApp(cfg config.EnvConfig, logger *slog.Logger) (*App, error) {
176183
177184 // Initialize MLflow client factory
178185 var mlflowFactory mlflowpkg.MLflowClientFactory
179- var mlflowState * mlflowmocks.MLflowState
180186 if cfg .MockMLflowClient {
181- mlflowState , err = mlflowmocks .SetupMLflow (logger )
187+ mlflowState , err : = mlflowmocks .SetupMLflow (logger )
182188 if err != nil {
183189 logger .Warn ("MLflow mock server not available, MLflow endpoints will fail on request" , "error" , err )
190+ } else {
191+ cleanupFuncs = append (cleanupFuncs , func () {
192+ logger .Info ("stopping MLflow server..." )
193+ mlflowmocks .CleanupMLflowState (mlflowState ,
194+ func (format string , args ... any ) { logger .Error (fmt .Sprintf (format , args ... )) },
195+ func (format string , args ... any ) { logger .Info (fmt .Sprintf (format , args ... )) },
196+ )
197+ })
184198 }
185199 mlflowFactory = mlflowmocks .NewMockClientFactory ()
186200 } else {
@@ -228,8 +242,7 @@ func NewApp(cfg config.EnvConfig, logger *slog.Logger) (*App, error) {
228242 rootCAs : rootCAs ,
229243 clusterDomain : clusterDomain ,
230244 fileUploadJobTracker : fileUploadJobTracker ,
231- testEnvState : testEnvState ,
232- mlflowState : mlflowState ,
245+ cleanupFuncs : cleanupFuncs ,
233246 }
234247 return app , nil
235248}
@@ -255,33 +268,9 @@ func resolveMLflowURL(cfg config.EnvConfig, logger *slog.Logger) string {
255268
256269func (app * App ) Shutdown () error {
257270 app .logger .Info ("shutting down app..." )
258-
259- if app .testEnvState != nil {
260- app .logger .Info ("stopping test environment..." )
261- k8smocks .CleanupTestEnvState (
262- app .testEnvState ,
263- func (format string , args ... interface {}) {
264- app .logger .Error (fmt .Sprintf (format , args ... ))
265- },
266- func (format string , args ... interface {}) {
267- app .logger .Info (fmt .Sprintf (format , args ... ))
268- },
269- )
271+ for i := len (app .cleanupFuncs ) - 1 ; i >= 0 ; i -- {
272+ app .cleanupFuncs [i ]()
270273 }
271-
272- if app .mlflowState != nil {
273- app .logger .Info ("stopping MLflow server..." )
274- mlflowmocks .CleanupMLflowState (
275- app .mlflowState ,
276- func (format string , args ... any ) {
277- app .logger .Error (fmt .Sprintf (format , args ... ))
278- },
279- func (format string , args ... any ) {
280- app .logger .Info (fmt .Sprintf (format , args ... ))
281- },
282- )
283- }
284-
285274 return nil
286275}
287276
0 commit comments