Conversation
Precondition work so the rust toolchain gates pass at all — the workspace was written before this box's rustfmt/clippy, and the current toolchain reformats it and fires lints on the existing code: - cargo fmt --all (mechanical, no semantic change) - studio-compose: implement std::iter::FromIterator for SkillsLibrary instead of an inherent from_iter (should_implement_trait) - studio-cp: derive Default for FleetRuntime (derivable_impls); use `?` in role_identity (question_mark); crate-level allow too_many_arguments for the flat dispatch-arg provision/observe API Same normalization the still-open PR openabdev#166 branch landed for the same gates; no behavior change intended. Generated with [Devin](https://devin.ai) Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
K8sDriver::apply produced a bare Deployment, so the pod's /acp listener had no address anywhere — the ACP auth key Studio wires into env was unusable, and AppliedService.webhook_urls came back empty. This applies a ClusterIP Service next to the Deployment whenever spec.acp_enabled is set: - Same oab-<name> slug and the Deployment's own pod labels as selector, sourced from one pod_labels() helper so the two can't drift - Exposes the gateway port the OpenAB binary defaults to (8080), the same default manifest::Ingress::container_port uses on the ECS side - Server-side apply with the same force field-manager the Deployment patch uses — idempotent, re-apply is a no-op - delete() removes the Service alongside the Deployment (404 = success, harmless when the agent never had acp enabled) ClusterIP, not NodePort/LoadBalancer: oab-<name>.<ns>.svc.cluster.local is reachable from the operator's machine on OrbStack and via kubectl port-forward everywhere else, without publishing the bearer-authed port on node IPs or a provisioned LB. Studio-side dynamic port-forward (the issue's candidate 2) stays a possible follow-up. The applied report now carries the agent's ws://…/acp URL, surfaced through ProvisionOutcome.webhook_urls and the deploy_provision* MCP results so the operator gets "an address to put next to the auth key". Generated with [Devin](https://devin.ai) Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Refs #155
K8sDriver::applypreviously produced a bareDeployment— the pod's/acplistener had no address anywhere in the cluster, so the ACP auth key the deploy writes into env had nothing to pair with andAppliedService.webhook_urlsalways came back empty.This change applies a
ClusterIPServicenext to theDeploymentwheneverspec.acpEnabledis set:oab-<name>slug as the Deployment; selector = the pod template labels, sourced from onepod_labels()helper so the two can't drift (unit-pinned against the built Deployment)default_container_portthe ECS ingress usesoabctlfield-manager + force as the Deployment — idempotent, re-apply is a no-opwebhook_urlsnow carriesws://oab-<name>.<ns>.svc.cluster.local:8080/acp, surfaced throughProvisionOutcome.webhook_urlsand thedeploy_provision*/deploy_provision_agentMCP results — "an address to put next to the auth key" foragents.tomldelete()removes the Service alongside the Deployment, and a re-apply withacpEnabledoff prunes a stale Service so it can't keep selecting pods that no longer listen on/acpClusterIP, deliberately not NodePort/LoadBalancer:
oab-<name>.<ns>.svc.cluster.localis reachable from the operator's machine on OrbStack (which routes*.svc.cluster.localand ClusterIPs to the host) and everywhere else viakubectl port-forward svc/oab-<name> 8080:8080— without publishing the bearer-authed port on node IPs or a provisioned LB. A Studio-side dynamic port-forward (the issue's candidate fix 2) remains a possible follow-up; the Service also gives that tunnel a stablesvc/target that survives pod restarts.Also closes a dispatch gap found in review:
deploy_deletehad no k8s branch, so a Studio-initiated delete of a k8s fleet agent never reachedK8sDriver— the Deployment (and now the Service) would dangle.t_deletenow mirrors thet_scalenamed-fleet dispatch from studio#161 viascp::delete_k8s_deployment.A separate commit normalizes workspace formatting + satisfies
clippy -D warningsunder the current toolchain (the base tree predates this rustfmt/clippy; same normalization as PR #166).Test plan
cargo fmt --all -- --checkcargo test --workspace(229 tests — new integration filecrates/oabctl/tests/k8s_acp_service.rscovers Service shape/selector/port/wire-shape, acp-off → no Service, ECS-runtime rejection, URL + slug; in-file unit test pins Service-selector ↔ pod-labels parity and the apply-vs-prune decision)cargo clippy --workspace --all-targets -- -D warningsGenerated with Devin