Skip to content

Commit 90993f6

Browse files
yroblataskbot
andauthored
change the default behaviour of proxyrunner (#1952)
* change the default behaviour of proxyrunner When using toolhive_use_configmap the operator will create a volume mount from the configmap, in the matching pod. Then proxyrunner needs to check if that file exists, and read the config from there instead of the old --from-configmap behaviour Closes: #1947 * changes from copilot * changes in env vars * remove not used methods --------- Co-authored-by: taskbot <[email protected]>
1 parent 8abada0 commit 90993f6

File tree

12 files changed

+744
-463
lines changed

12 files changed

+744
-463
lines changed

cmd/thv-operator/controllers/mcpserver_controller.go

Lines changed: 23 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -747,14 +747,13 @@ func (r *MCPServerReconciler) deploymentForMCPServer(ctx context.Context, m *mcp
747747
// Prepare container args
748748
args := []string{"run", "--foreground=true"}
749749

750+
// Prepare container volume mounts
751+
volumeMounts := []corev1.VolumeMount{}
752+
volumes := []corev1.Volume{}
753+
750754
// Check if global ConfigMap mode is enabled via environment variable
751755
useConfigMap := os.Getenv("TOOLHIVE_USE_CONFIGMAP") == trueValue
752756
if useConfigMap {
753-
// Use the operator-created ConfigMap (format: {name}-runconfig)
754-
configMapName := fmt.Sprintf("%s-runconfig", m.Name)
755-
configMapRef := fmt.Sprintf("%s/%s", m.Namespace, configMapName)
756-
args = append(args, fmt.Sprintf("--from-configmap=%s", configMapRef))
757-
758757
// Also add pod template patch for secrets (same as regular flags approach)
759758
finalPodTemplateSpec := NewMCPServerPodTemplateSpecBuilder(m.Spec.PodTemplateSpec).
760759
WithSecrets(m.Spec.Secrets).
@@ -769,6 +768,25 @@ func (r *MCPServerReconciler) deploymentForMCPServer(ctx context.Context, m *mcp
769768
args = append(args, fmt.Sprintf("--k8s-pod-patch=%s", string(podTemplatePatch)))
770769
}
771770
}
771+
772+
// Add volume mount for ConfigMap
773+
configMapName := fmt.Sprintf("%s-runconfig", m.Name)
774+
volumeMounts = append(volumeMounts, corev1.VolumeMount{
775+
Name: "runconfig",
776+
MountPath: "/etc/runconfig",
777+
ReadOnly: true,
778+
})
779+
780+
volumes = append(volumes, corev1.Volume{
781+
Name: "runconfig",
782+
VolumeSource: corev1.VolumeSource{
783+
ConfigMap: &corev1.ConfigMapVolumeSource{
784+
LocalObjectReference: corev1.LocalObjectReference{
785+
Name: configMapName,
786+
},
787+
},
788+
},
789+
})
772790
} else {
773791
// Use individual configuration flags (existing behavior)
774792
args = append(args, fmt.Sprintf("--proxy-port=%d", m.Spec.Port))
@@ -909,10 +927,6 @@ func (r *MCPServerReconciler) deploymentForMCPServer(ctx context.Context, m *mcp
909927
}
910928
}
911929

912-
// Prepare container volume mounts
913-
volumeMounts := []corev1.VolumeMount{}
914-
volumes := []corev1.Volume{}
915-
916930
// Add volume mounts for user-defined volumes
917931
for _, v := range m.Spec.Volumes {
918932
volumeMounts = append(volumeMounts, corev1.VolumeMount{
Lines changed: 138 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,138 @@
1+
package app
2+
3+
import (
4+
"context"
5+
"fmt"
6+
7+
"github.com/spf13/cobra"
8+
9+
"github.com/stacklok/toolhive/pkg/container/runtime"
10+
"github.com/stacklok/toolhive/pkg/environment"
11+
"github.com/stacklok/toolhive/pkg/registry"
12+
"github.com/stacklok/toolhive/pkg/runner"
13+
"github.com/stacklok/toolhive/pkg/transport"
14+
"github.com/stacklok/toolhive/pkg/transport/types"
15+
"github.com/stacklok/toolhive/pkg/workloads"
16+
)
17+
18+
// TODO: This function should be deprecated - CLI flags will be removed in favor of file-based configuration only
19+
// runWithFlagsBasedConfig handles execution using CLI flags (legacy approach)
20+
func runWithFlagsBasedConfig(
21+
ctx context.Context,
22+
mcpServerImage string,
23+
cmdArgs []string,
24+
validatedHost string,
25+
rt runtime.Runtime,
26+
debugMode bool,
27+
envVarValidator runner.EnvVarValidator,
28+
imageMetadata *registry.ImageMetadata,
29+
) error {
30+
envVarsMap, err := environment.ParseEnvironmentVariables(runFlags.runEnv)
31+
if err != nil {
32+
return fmt.Errorf("failed to parse environment variables: %v", err)
33+
}
34+
35+
// Build options using CLI flags
36+
opts := []runner.RunConfigBuilderOption{
37+
runner.WithRuntime(rt),
38+
runner.WithDebug(debugMode),
39+
runner.WithCmdArgs(cmdArgs),
40+
runner.WithImage(mcpServerImage),
41+
runner.WithName(runFlags.runName),
42+
runner.WithTransportAndPorts(runFlags.runTransport, runFlags.runProxyPort, runFlags.runTargetPort),
43+
runner.WithHost(validatedHost),
44+
runner.WithTargetHost(transport.LocalhostIPv4),
45+
runner.WithProxyMode(types.ProxyMode(runFlags.runProxyMode)),
46+
runner.WithVolumes(runFlags.runVolumes),
47+
runner.WithSecrets(runFlags.runSecrets),
48+
runner.WithAuthzConfigPath(runFlags.runAuthzConfig),
49+
runner.WithAuditConfigPath(runFlags.runAuditConfig),
50+
runner.WithAuditEnabled(runFlags.runEnableAudit, runFlags.runAuditConfig),
51+
runner.WithPermissionProfileNameOrPath(runFlags.runPermissionProfile),
52+
runner.WithNetworkIsolation(runFlags.runIsolateNetwork),
53+
runner.WithEnvVars(envVarsMap),
54+
runner.WithToolsFilter(runFlags.runToolsFilter),
55+
runner.WithEnvFilesFromDirectory(runFlags.runEnvFileDir),
56+
runner.WithK8sPodPatch(runFlags.runK8sPodPatch),
57+
runner.WithOIDCConfig(
58+
runFlags.oidcIssuer,
59+
runFlags.oidcAudience,
60+
runFlags.oidcJwksURL,
61+
runFlags.oidcIntrospectionURL,
62+
runFlags.oidcClientID,
63+
runFlags.oidcClientSecret,
64+
runFlags.runThvCABundle,
65+
runFlags.runJWKSAuthTokenFile,
66+
runFlags.runResourceURL,
67+
runFlags.runJWKSAllowPrivateIP,
68+
),
69+
runner.WithTelemetryConfig(
70+
runFlags.runOtelEndpoint,
71+
runFlags.enablePrometheusMetricsPath,
72+
runFlags.runOtelTracingEnabled,
73+
runFlags.runOtelMetricsEnabled,
74+
runFlags.runOtelServiceName,
75+
runFlags.runOtelTracingSamplingRate,
76+
runFlags.runOtelHeaders,
77+
runFlags.runOtelInsecure,
78+
[]string{}, // CLI flags don't include telemetry environment variables, pass empty slice
79+
),
80+
}
81+
82+
runConfig, err := runner.NewRunConfigBuilder(ctx, imageMetadata, envVarsMap, envVarValidator, opts...)
83+
if err != nil {
84+
return fmt.Errorf("failed to create RunConfig: %v", err)
85+
}
86+
87+
workloadManager, err := workloads.NewManagerFromRuntime(rt)
88+
if err != nil {
89+
return fmt.Errorf("failed to create workload manager: %v", err)
90+
}
91+
return workloadManager.RunWorkload(ctx, runConfig)
92+
}
93+
94+
// runWithFileBasedConfig handles execution when a runconfig.json file is found.
95+
// Uses config from file exactly as-is, ignoring all CLI configuration flags.
96+
// Only uses essential non-configuration inputs: image, command args, and --k8s-pod-patch.
97+
func runWithFileBasedConfig(
98+
ctx context.Context,
99+
cmd *cobra.Command,
100+
mcpServerImage string,
101+
cmdArgs []string,
102+
config *runner.RunConfig,
103+
rt runtime.Runtime,
104+
debugMode bool,
105+
envVarValidator runner.EnvVarValidator,
106+
imageMetadata *registry.ImageMetadata,
107+
) error {
108+
// Use the file config directly with minimal essential overrides
109+
config.Image = mcpServerImage
110+
config.CmdArgs = cmdArgs
111+
config.Deployer = rt
112+
config.Debug = debugMode
113+
114+
// Apply --k8s-pod-patch flag if provided (essential for K8s operation)
115+
if cmd.Flags().Changed("k8s-pod-patch") && runFlags.runK8sPodPatch != "" {
116+
config.K8sPodTemplatePatch = runFlags.runK8sPodPatch
117+
}
118+
119+
// Validate environment variables using the provided validator
120+
if envVarValidator != nil {
121+
validatedEnvVars, err := envVarValidator.Validate(ctx, imageMetadata, config, config.EnvVars)
122+
if err != nil {
123+
return fmt.Errorf("failed to validate environment variables: %v", err)
124+
}
125+
config.EnvVars = validatedEnvVars
126+
}
127+
128+
// Apply image metadata overrides if needed (similar to what the builder does)
129+
if imageMetadata != nil && config.Name == "" {
130+
config.Name = imageMetadata.Name
131+
}
132+
133+
workloadManager, err := workloads.NewManagerFromRuntime(rt)
134+
if err != nil {
135+
return fmt.Errorf("failed to create workload manager: %v", err)
136+
}
137+
return workloadManager.RunWorkload(ctx, config)
138+
}

0 commit comments

Comments
 (0)