-
Notifications
You must be signed in to change notification settings - Fork 106
fix(security,api-server,control-plane): CodeRabbit fixes, deletecollection fallback, idempotent agent start #1290
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
9412bf5
6b1fb80
30ad254
64bd79d
32c1ed2
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -22,6 +22,7 @@ type SessionService interface { | |||||||||||||||||||||||||||||||||||
| UpdateStatus(ctx context.Context, id string, patch *SessionStatusPatchRequest) (*Session, *errors.ServiceError) | ||||||||||||||||||||||||||||||||||||
| Start(ctx context.Context, id string) (*Session, *errors.ServiceError) | ||||||||||||||||||||||||||||||||||||
| Stop(ctx context.Context, id string) (*Session, *errors.ServiceError) | ||||||||||||||||||||||||||||||||||||
| ActiveByAgentID(ctx context.Context, agentID string) (*Session, *errors.ServiceError) | ||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||
| FindByIDs(ctx context.Context, ids []string) (SessionList, *errors.ServiceError) | ||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||
|
|
@@ -265,6 +266,14 @@ func (s *sqlSessionService) Start(ctx context.Context, id string) (*Session, *er | |||||||||||||||||||||||||||||||||||
| return session, nil | ||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||
| func (s *sqlSessionService) ActiveByAgentID(ctx context.Context, agentID string) (*Session, *errors.ServiceError) { | ||||||||||||||||||||||||||||||||||||
| session, err := s.sessionDao.ActiveByAgentID(ctx, agentID) | ||||||||||||||||||||||||||||||||||||
| if err != nil { | ||||||||||||||||||||||||||||||||||||
| return nil, nil | ||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||
| return session, nil | ||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||
|
Comment on lines
+269
to
+275
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Swallowing all errors breaks idempotency under DB instability. Returning Consider distinguishing Proposed fix func (s *sqlSessionService) ActiveByAgentID(ctx context.Context, agentID string) (*Session, *errors.ServiceError) {
session, err := s.sessionDao.ActiveByAgentID(ctx, agentID)
if err != nil {
+ if errors.Is(err, gorm.ErrRecordNotFound) {
+ return nil, nil
+ }
+ return nil, errors.GeneralError("failed to check active session: %v", err)
- return nil, nil
}
return session, nil
}Then update the handler to fail fast on real errors instead of proceeding to create. 📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||
| func (s *sqlSessionService) Stop(ctx context.Context, id string) (*Session, *errors.ServiceError) { | ||||||||||||||||||||||||||||||||||||
| session, err := s.sessionDao.Get(ctx, id) | ||||||||||||||||||||||||||||||||||||
| if err != nil { | ||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -40,6 +40,9 @@ type KubeReconcilerConfig struct { | |
| CPRuntimeNamespace string | ||
| CPTokenURL string | ||
| CPTokenPublicKey string | ||
| HTTPProxy string | ||
| HTTPSProxy string | ||
| NoProxy string | ||
| } | ||
|
|
||
| type SimpleKubeReconciler struct { | ||
|
|
@@ -441,8 +444,12 @@ func (r *SimpleKubeReconciler) ensurePod(ctx context.Context, namespace string, | |
| } | ||
|
|
||
| if useMCPSidecar { | ||
| containers = append(containers, r.buildMCPSidecar(session.ID)) | ||
| r.logger.Info().Str("session_id", session.ID).Msg("MCP sidecar enabled for session") | ||
| if r.cfg.CPTokenURL == "" || r.cfg.CPTokenPublicKey == "" { | ||
| r.logger.Warn().Str("session_id", session.ID).Msg("MCP sidecar skipped: CP_TOKEN_URL or CPTokenPublicKey not configured") | ||
| } else { | ||
| containers = append(containers, r.buildMCPSidecar(session.ID)) | ||
| r.logger.Info().Str("session_id", session.ID).Msg("MCP sidecar enabled for session") | ||
| } | ||
|
Comment on lines
+447
to
+452
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Don’t advertise MCP when the sidecar is skipped. Lines 447-452 can omit the MCP container, but Suggested fix- useMCPSidecar := r.cfg.MCPImage != ""
+ useMCPSidecar := r.cfg.MCPImage != "" && r.cfg.CPTokenURL != "" && r.cfg.CPTokenPublicKey != ""
containers := []interface{}{
map[string]interface{}{
"name": "ambient-code-runner",
@@
- if useMCPSidecar {
- if r.cfg.CPTokenURL == "" || r.cfg.CPTokenPublicKey == "" {
- r.logger.Warn().Str("session_id", session.ID).Msg("MCP sidecar skipped: CP_TOKEN_URL or CPTokenPublicKey not configured")
- } else {
- containers = append(containers, r.buildMCPSidecar(session.ID))
- r.logger.Info().Str("session_id", session.ID).Msg("MCP sidecar enabled for session")
- }
+ if r.cfg.MCPImage != "" && !useMCPSidecar {
+ r.logger.Warn().Str("session_id", session.ID).Msg("MCP sidecar skipped: CP_TOKEN_URL or CPTokenPublicKey not configured")
+ }
+ if useMCPSidecar {
+ containers = append(containers, r.buildMCPSidecar(session.ID))
+ r.logger.Info().Str("session_id", session.ID).Msg("MCP sidecar enabled for session")
}🤖 Prompt for AI Agents |
||
| } | ||
|
|
||
| pod := &unstructured.Unstructured{ | ||
|
|
@@ -637,6 +644,16 @@ func (r *SimpleKubeReconciler) buildEnv(ctx context.Context, session types.Sessi | |
| } | ||
| } | ||
|
|
||
| if r.cfg.HTTPProxy != "" { | ||
| env = append(env, envVar("HTTP_PROXY", r.cfg.HTTPProxy)) | ||
| } | ||
| if r.cfg.HTTPSProxy != "" { | ||
| env = append(env, envVar("HTTPS_PROXY", r.cfg.HTTPSProxy)) | ||
| } | ||
| if r.cfg.NoProxy != "" { | ||
| env = append(env, envVar("NO_PROXY", r.cfg.NoProxy)) | ||
| } | ||
|
Comment on lines
+647
to
+655
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Forward lowercase proxy vars too, not just uppercase. This path only injects Suggested fix--- a/components/ambient-control-plane/internal/config/config.go
+++ b/components/ambient-control-plane/internal/config/config.go
@@
- HTTPProxy: os.Getenv("HTTP_PROXY"),
- HTTPSProxy: os.Getenv("HTTPS_PROXY"),
- NoProxy: os.Getenv("NO_PROXY"),
+ HTTPProxy: firstEnv("HTTP_PROXY", "http_proxy"),
+ HTTPSProxy: firstEnv("HTTPS_PROXY", "https_proxy"),
+ NoProxy: firstEnv("NO_PROXY", "no_proxy"),
}
@@
func envOrDefault(key, fallback string) string {
if v := os.Getenv(key); v != "" {
return v
}
return fallback
}
+
+func firstEnv(keys ...string) string {
+ for _, key := range keys {
+ if v := os.Getenv(key); v != "" {
+ return v
+ }
+ }
+ return ""
+}--- a/components/ambient-control-plane/internal/reconciler/kube_reconciler.go
+++ b/components/ambient-control-plane/internal/reconciler/kube_reconciler.go
@@
if r.cfg.HTTPProxy != "" {
- env = append(env, envVar("HTTP_PROXY", r.cfg.HTTPProxy))
+ env = append(env,
+ envVar("HTTP_PROXY", r.cfg.HTTPProxy),
+ envVar("http_proxy", r.cfg.HTTPProxy),
+ )
}
if r.cfg.HTTPSProxy != "" {
- env = append(env, envVar("HTTPS_PROXY", r.cfg.HTTPSProxy))
+ env = append(env,
+ envVar("HTTPS_PROXY", r.cfg.HTTPSProxy),
+ envVar("https_proxy", r.cfg.HTTPSProxy),
+ )
}
if r.cfg.NoProxy != "" {
- env = append(env, envVar("NO_PROXY", r.cfg.NoProxy))
+ env = append(env,
+ envVar("NO_PROXY", r.cfg.NoProxy),
+ envVar("no_proxy", r.cfg.NoProxy),
+ )
}Verify the current code only handles uppercase proxy vars end-to-end: #!/bin/bash
set -euo pipefail
echo "== Proxy env loading from config =="
rg -n 'os\.Getenv\("(HTTP_PROXY|HTTPS_PROXY|NO_PROXY|http_proxy|https_proxy|no_proxy)"\)' \
components/ambient-control-plane/internal/config/config.go
echo
echo "== Proxy env injection into pods =="
rg -n 'envVar\("(HTTP_PROXY|HTTPS_PROXY|NO_PROXY|http_proxy|https_proxy|no_proxy)"' \
components/ambient-control-plane/internal/reconciler/kube_reconciler.goAlso applies to: 845-853 🤖 Prompt for AI Agents |
||
|
|
||
| return env | ||
| } | ||
|
|
||
|
|
@@ -825,6 +842,15 @@ func (r *SimpleKubeReconciler) buildMCPSidecar(sessionID string) interface{} { | |
| envVar("AMBIENT_CP_TOKEN_PUBLIC_KEY", r.cfg.CPTokenPublicKey), | ||
| envVar("SESSION_ID", sessionID), | ||
| } | ||
| if r.cfg.HTTPProxy != "" { | ||
| env = append(env, envVar("HTTP_PROXY", r.cfg.HTTPProxy)) | ||
| } | ||
| if r.cfg.HTTPSProxy != "" { | ||
| env = append(env, envVar("HTTPS_PROXY", r.cfg.HTTPSProxy)) | ||
| } | ||
| if r.cfg.NoProxy != "" { | ||
| env = append(env, envVar("NO_PROXY", r.cfg.NoProxy)) | ||
| } | ||
| return map[string]interface{}{ | ||
| "name": "ambient-mcp", | ||
| "image": mcpImage, | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Handler should propagate errors from ActiveByAgentID check.
Currently discards the error with
_. If the service is updated to return real errors (per comment onservice.go), this should be:This ensures idempotency isn't silently bypassed during DB issues.
🤖 Prompt for AI Agents