diff --git a/components/manifests/templates/template-operator.yaml b/components/manifests/templates/template-operator.yaml deleted file mode 100644 index 2316dc549..000000000 --- a/components/manifests/templates/template-operator.yaml +++ /dev/null @@ -1,1456 +0,0 @@ -apiVersion: template.openshift.io/v1 -kind: Template -metadata: - name: ambient-code-operator - annotations: - description: Ambient Code Platform - Operator -parameters: -- name: IMAGE_TAG - description: Image tag - required: true -- name: IMAGE_OPERATOR - value: quay.io/redhat-services-prod/hcm-eng-prod-tenant/ambient-code-main/ambient-code-operator-main -- name: IMAGE_AMBIENT_RUNNER - value: quay.io/redhat-services-prod/hcm-eng-prod-tenant/ambient-code-main/ambient-code-ambient-runner-main -- name: ANTHROPIC_VERTEX_PROJECT_ID - value: itpc-gcp-hcm-pe-eng-claude -objects: -- apiVersion: apiextensions.k8s.io/v1 - kind: CustomResourceDefinition - metadata: - name: agenticsessions.vteam.ambient-code - spec: - group: vteam.ambient-code - names: - kind: AgenticSession - plural: agenticsessions - shortNames: - - as - singular: agenticsession - scope: Namespaced - versions: - - name: v1alpha1 - schema: - openAPIV3Schema: - properties: - spec: - properties: - activeWorkflow: - description: Active workflow configuration for dynamic workflow switching - properties: - branch: - default: main - description: Branch to clone - type: string - gitUrl: - description: Git repository URL for the workflow - type: string - path: - description: Optional path within repo (for repos with multiple workflows) - type: string - type: object - displayName: - description: A descriptive display name for the agentic session generated from prompt and website - type: string - environmentVariables: - additionalProperties: - type: string - description: 'Key-value pairs injected as environment variables into all pod containers (init-hydrate, runner, state-sync). Reserved variables (SESSION_NAME, S3_ENDPOINT, S3_BUCKET, AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, NAMESPACE, SYNC_INTERVAL) cannot be overridden in init-hydrate and state-sync containers. Common conventions: RUNNER_TYPE identifies the runner framework (e.g. "claude-agent-sdk", "gemini-cli"), RUNNER_STATE_DIR sets the framework state directory relative to /workspace (defaults to ".claude").' - type: object - inactivityTimeout: - description: Seconds of inactivity before auto-stopping a session. 0 disables auto-shutdown. If omitted, falls back to project-level inactivityTimeoutSeconds, then 24h default. - minimum: 0 - type: integer - initialPrompt: - description: Initial prompt used only on first SDK invocation for brand new sessions (ignored on continuations or workflow restarts). - type: string - llmSettings: - description: LLM configuration settings - properties: - maxTokens: - default: 4000 - type: integer - model: - default: claude-3-7-sonnet-latest - type: string - temperature: - default: 0.7 - type: number - type: object - repos: - description: List of Git repositories to clone and work with - items: - properties: - autoPush: - default: false - description: When true, automatically commit and push changes to this repository after session completion - type: boolean - branch: - default: main - description: Branch to checkout - type: string - url: - description: Git repository URL - type: string - required: - - url - type: object - type: array - stopOnRunFinished: - description: When true, automatically stop the session when the agent completes its run (RUN_FINISHED event). Useful for one-shot tasks triggered by automation. - type: boolean - timeout: - default: 300 - description: Timeout in seconds for the agentic session - type: integer - userContext: - description: Authenticated caller identity captured at creation time (used for authorization and audit) - properties: - displayName: - description: Human-readable display name - type: string - groups: - description: Group memberships of the user - items: - type: string - type: array - userId: - description: Stable user identifier (from SSO, always overwritten from auth token) - type: string - type: object - type: object - status: - properties: - completionTime: - description: Timestamp when the session reached a terminal phase. - format: date-time - type: string - conditions: - description: Detailed condition set describing reconciliation progress. - items: - properties: - lastTransitionTime: - format: date-time - type: string - message: - type: string - observedGeneration: - format: int64 - type: integer - reason: - type: string - status: - enum: - - 'True' - - 'False' - - Unknown - type: string - type: - type: string - required: - - type - - status - type: object - type: array - lastActivityTime: - description: Timestamp of last recorded AG-UI activity in this session. - format: date-time - type: string - observedGeneration: - description: Spec generation that the operator has fully reconciled. - format: int64 - type: integer - phase: - default: Pending - enum: - - Pending - - Creating - - Running - - Stopping - - Stopped - - Completed - - Failed - type: string - reconciledRepos: - description: Current reconciliation state for each repository. - items: - properties: - branch: - description: 'DEPRECATED: Use currentActiveBranch instead' - type: string - branches: - description: All local branches available in this repository - items: - type: string - type: array - clonedAt: - format: date-time - type: string - currentActiveBranch: - description: Currently checked out branch (polled from filesystem) - type: string - defaultBranch: - description: Default branch of the remote repository (e.g., main, master) - type: string - name: - type: string - status: - enum: - - Cloning - - Ready - - Failed - type: string - url: - type: string - type: object - type: array - reconciledWorkflow: - description: Current reconciliation state for the active workflow. - properties: - appliedAt: - format: date-time - type: string - branch: - type: string - gitUrl: - type: string - path: - description: Optional path within the workflow repository - type: string - status: - enum: - - Cloning - - Active - - Failed - type: string - type: object - sdkRestartCount: - description: Number of times the SDK has been restarted during this session. - type: integer - sdkSessionId: - description: SDK session identifier captured for resume support. - type: string - startTime: - description: Timestamp when the session runner started executing. - format: date-time - type: string - stoppedReason: - description: Reason the session was stopped. - enum: - - user - - inactivity - type: string - type: object - type: object - served: true - storage: true - subresources: - status: {} -- apiVersion: apiextensions.k8s.io/v1 - kind: CustomResourceDefinition - metadata: - name: projectsettings.vteam.ambient-code - spec: - group: vteam.ambient-code - names: - kind: ProjectSettings - plural: projectsettings - shortNames: - - ps - singular: projectsetting - scope: Namespaced - versions: - - additionalPrinterColumns: - - jsonPath: .metadata.creationTimestamp - name: Age - type: date - name: v1alpha1 - schema: - openAPIV3Schema: - properties: - spec: - properties: - groupAccess: - description: Group access configuration creating RoleBindings - items: - properties: - groupName: - description: Name of the group to grant access - type: string - role: - description: Role to assign to the group (admin/edit/view) - enum: - - admin - - edit - - view - type: string - required: - - groupName - - role - type: object - type: array - inactivityTimeoutSeconds: - default: 86400 - description: Default inactivity timeout for sessions in this project (seconds). 0 disables. Overridden by session-level spec.inactivityTimeout. - minimum: 0 - type: integer - repositories: - description: Git repositories configured for this project - items: - properties: - branch: - description: Optional branch override (defaults to repository's default branch) - type: string - provider: - description: Git hosting provider (auto-detected from URL if not specified) - enum: - - github - - gitlab - type: string - url: - description: Repository URL (HTTPS or SSH format) - type: string - required: - - url - type: object - type: array - runnerSecretsName: - description: Name of the Kubernetes Secret in this namespace that stores runner configuration key/value pairs - type: string - required: - - groupAccess - type: object - status: - properties: - groupBindingsCreated: - description: Number of group RoleBindings successfully created - minimum: 0 - type: integer - limitRangeReady: - description: Whether the default LimitRange for CA bin-packing is provisioned - type: boolean - scheduledSessionRBACReady: - description: Whether RBAC for scheduled session triggers is provisioned - type: boolean - type: object - type: object - x-kubernetes-validations: - - message: metadata.name must be 'projectsettings' (singleton per namespace) - rule: self.metadata.name == 'projectsettings' - served: true - storage: true - subresources: - status: {} -- apiVersion: v1 - kind: ServiceAccount - metadata: - name: agentic-operator - namespace: ambient-code -- apiVersion: v1 - kind: ServiceAccount - metadata: - labels: - app: ambient-api-server - name: ambient-api-server - namespace: ambient-code -- apiVersion: v1 - kind: ServiceAccount - metadata: - name: backend-api - namespace: ambient-code -- apiVersion: v1 - kind: ServiceAccount - metadata: - annotations: - serviceaccounts.openshift.io/oauth-redirectreference.frontend: '{"kind":"OAuthRedirectReference","apiVersion":"v1","reference":{"kind":"Route","name":"frontend-route"}}' - name: frontend - namespace: ambient-code -- apiVersion: v1 - kind: ServiceAccount - metadata: - labels: - app: public-api - name: public-api - namespace: ambient-code -- apiVersion: rbac.authorization.k8s.io/v1 - kind: ClusterRole - metadata: - name: agentic-operator - rules: - - apiGroups: - - vteam.ambient-code - resources: - - agenticsessions - verbs: - - get - - list - - watch - - create - - update - - patch - - apiGroups: - - vteam.ambient-code - resources: - - agenticsessions/status - verbs: - - update - - apiGroups: - - vteam.ambient-code - resources: - - projectsettings - verbs: - - get - - list - - watch - - create - - apiGroups: - - vteam.ambient-code - resources: - - projectsettings/status - verbs: - - update - - apiGroups: - - '' - resources: - - namespaces - verbs: - - get - - list - - watch - - apiGroups: - - batch - resources: - - jobs - verbs: - - get - - list - - watch - - create - - delete - - apiGroups: - - '' - resources: - - pods - verbs: - - get - - list - - watch - - create - - delete - - deletecollection - - apiGroups: - - '' - resources: - - pods/log - verbs: - - get - - apiGroups: - - '' - resources: - - persistentvolumeclaims - verbs: - - get - - list - - create - - delete - - apiGroups: - - '' - resources: - - services - verbs: - - get - - list - - watch - - create - - delete - - apiGroups: - - apps - resources: - - deployments - verbs: - - get - - list - - watch - - create - - apiGroups: - - '' - resources: - - serviceaccounts - verbs: - - get - - create - - delete - - apiGroups: - - '' - resources: - - serviceaccounts/token - verbs: - - create - - apiGroups: - - rbac.authorization.k8s.io - resources: - - roles - verbs: - - get - - create - - update - - delete - - apiGroups: - - rbac.authorization.k8s.io - resources: - - rolebindings - verbs: - - get - - create - - delete - - apiGroups: - - '' - resources: - - limitranges - verbs: - - get - - create - - apiGroups: - - '' - resources: - - configmaps - verbs: - - get - - apiGroups: - - '' - resources: - - secrets - verbs: - - get - - create - - delete - - update - # MLflow experiment tracking permissions (namespace-scoped CRDs) - # Required to grant MLflow access to session runner service accounts - # Sessions need these permissions to log experiments/runs to MLflow tracking server - # Uses Kubeflow MLflow Operator CRDs for Kubernetes-native RBAC authentication - - apiGroups: - - mlflow.kubeflow.org - resources: - - experiments - - runs - verbs: - - get - - list - - watch - - create - - update - - patch - - delete - # NetworkPolicy permissions for isolating runner pods - - apiGroups: - - networking.k8s.io - resources: - - networkpolicies - verbs: - - get - - list - - create - - delete -- apiVersion: rbac.authorization.k8s.io/v1 - kind: ClusterRole - metadata: - labels: - rbac.authorization.k8s.io/aggregate-to-admin: 'true' - name: agenticsessions-aggregate-to-admin - rules: - - apiGroups: - - vteam.ambient-code - resources: - - agenticsessions - verbs: - - '*' - - apiGroups: - - vteam.ambient-code - resources: - - agenticsessions/status - verbs: - - get - - update - - patch -- apiVersion: rbac.authorization.k8s.io/v1 - kind: ClusterRole - metadata: - name: ambient-frontend-auth - rules: - - apiGroups: - - authentication.k8s.io - resources: - - tokenreviews - verbs: - - create - - apiGroups: - - authorization.k8s.io - resources: - - subjectaccessreviews - verbs: - - create -- apiVersion: rbac.authorization.k8s.io/v1 - kind: ClusterRole - metadata: - name: ambient-namespace-viewer - rules: - - apiGroups: - - project.openshift.io - resources: - - projects - verbs: - - get - - list - - watch -- apiVersion: rbac.authorization.k8s.io/v1 - kind: ClusterRole - metadata: - name: ambient-project-admin - rules: - - apiGroups: - - vteam.ambient-code - resources: - - projectsettings - verbs: - - get - - list - - watch - - create - - update - - patch - - delete - - apiGroups: - - vteam.ambient-code - resources: - - agenticsessions - verbs: - - get - - list - - watch - - create - - update - - patch - - delete - - apiGroups: - - vteam.ambient-code - resources: - - projectsettings/status - verbs: - - get - - list - - watch - - update - - patch - - apiGroups: - - vteam.ambient-code - resources: - - agenticsessions/status - verbs: - - get - - list - - watch - - apiGroups: - - '' - resources: - - secrets - - configmaps - verbs: - - get - - list - - watch - - create - - update - - patch - - delete - - apiGroups: - - '' - resources: - - serviceaccounts - verbs: - - get - - list - - watch - - create - - update - - patch - - delete - - apiGroups: - - '' - resources: - - serviceaccounts/token - verbs: - - create - - apiGroups: - - rbac.authorization.k8s.io - resources: - - roles - - rolebindings - verbs: - - get - - list - - watch - - create - - update - - patch - - delete - - apiGroups: - - batch - resources: - - jobs - verbs: - - get - - list - - watch - - create - - update - - patch - - delete - - apiGroups: - - '' - resources: - - pods - - pods/log - verbs: - - get - - list - - watch - - apiGroups: - - '' - resources: - - events - verbs: - - get - - list - - watch - - apiGroups: - - project.openshift.io - resources: - - projects - verbs: - - get - - list - - watch - - apiGroups: - - '' - resources: - - persistentvolumeclaims - verbs: - - get - - list - - watch - - delete - - apiGroups: - - '' - resources: - - services - verbs: - - get - - list - - watch - - delete - - apiGroups: - - apps - resources: - - deployments - verbs: - - get - - list - - watch - - delete -- apiVersion: rbac.authorization.k8s.io/v1 - kind: ClusterRole - metadata: - name: ambient-project-edit - rules: - - apiGroups: - - vteam.ambient-code - resources: - - agenticsessions - verbs: - - get - - list - - watch - - create - - update - - patch - - apiGroups: - - vteam.ambient-code - resources: - - agenticsessions/status - verbs: - - get - - list - - watch - - apiGroups: - - vteam.ambient-code - resources: - - projectsettings - verbs: - - get - - list - - watch - - apiGroups: - - project.openshift.io - resources: - - projects - verbs: - - get - - list - - watch - - apiGroups: - - '' - resources: - - configmaps - verbs: - - get - - apiGroups: - - '' - resourceNames: - - ambient-runner-secrets - resources: - - secrets - verbs: - - get - - apiGroups: - - '' - resources: - - secrets - verbs: - - create - - apiGroups: - - batch - resources: - - jobs - verbs: - - get - - list - - watch - - delete - - apiGroups: - - '' - resources: - - pods - - pods/log - verbs: - - get - - list - - watch - - apiGroups: - - '' - resources: - - events - verbs: - - get - - list - - watch - - apiGroups: - - '' - resources: - - persistentvolumeclaims - verbs: - - get - - list - - watch - - apiGroups: - - '' - resources: - - services - verbs: - - get - - list - - watch - - apiGroups: - - apps - resources: - - deployments - verbs: - - get - - list - - watch - - apiGroups: - - '' - resources: - - serviceaccounts - verbs: - - get - - list - - create - - update - - patch - - apiGroups: - - rbac.authorization.k8s.io - resources: - - roles - - rolebindings - verbs: - - get - - list - - create - - update - - patch - - delete - - apiGroups: - - '' - resources: - - serviceaccounts/token - verbs: - - create -- apiVersion: rbac.authorization.k8s.io/v1 - kind: ClusterRole - metadata: - name: ambient-project-view - rules: - - apiGroups: - - vteam.ambient-code - resources: - - agenticsessions - - projectsettings - verbs: - - get - - list - - watch - - apiGroups: - - vteam.ambient-code - resources: - - agenticsessions/status - - projectsettings/status - verbs: - - get - - list - - watch - - apiGroups: - - project.openshift.io - resources: - - projects - verbs: - - get - - list - - watch - - apiGroups: - - batch - resources: - - jobs - verbs: - - get - - list - - watch - - apiGroups: - - '' - resources: - - pods - - pods/log - verbs: - - get - - list - - watch - - apiGroups: - - '' - resources: - - events - verbs: - - get - - list - - watch - - apiGroups: - - '' - resources: - - persistentvolumeclaims - - services - verbs: - - get - - list - - watch - - apiGroups: - - apps - resources: - - deployments - verbs: - - get - - list - - watch -- apiVersion: rbac.authorization.k8s.io/v1 - kind: ClusterRole - metadata: - name: backend-api - rules: - - apiGroups: - - vteam.ambient-code - resources: - - agenticsessions - verbs: - - get - - list - - watch - - create - - update - - patch - - delete - - apiGroups: - - vteam.ambient-code - resources: - - agenticsessions/status - verbs: - - get - - update - - patch - - apiGroups: - - '' - resources: - - serviceaccounts - verbs: - - get - - list - - create - - update - - patch - - apiGroups: - - '' - resources: - - serviceaccounts/token - verbs: - - create - - apiGroups: - - authentication.k8s.io - resources: - - tokenreviews - verbs: - - create - - apiGroups: - - rbac.authorization.k8s.io - resources: - - roles - - rolebindings - verbs: - - get - - list - - create - - update - - patch - - delete - - apiGroups: - - rbac.authorization.k8s.io - resourceNames: - - ambient-project-admin - - ambient-project-edit - - ambient-project-view - resources: - - clusterroles - verbs: - - bind - - apiGroups: - - '' - resources: - - secrets - verbs: - - get - - list - - create - - update - - patch - - delete - - apiGroups: - - '' - resources: - - configmaps - verbs: - - get - - create - - update - - patch - - apiGroups: - - '' - resources: - - namespaces - verbs: - - get - - list - - create - - update - - patch - - delete - - apiGroups: - - project.openshift.io - resources: - - projects - verbs: - - get - - list - - watch - - update - - patch - - apiGroups: - - batch - resources: - - jobs - verbs: - - get - - list - - watch - - create - - delete - - apiGroups: - - batch - resources: - - cronjobs - verbs: - - get - - list - - watch - - create - - update - - patch - - delete - - apiGroups: - - '' - resources: - - pods - verbs: - - get - - list - - watch - - create - - delete - - deletecollection - - apiGroups: - - '' - resources: - - pods/log - verbs: - - get - - apiGroups: - - '' - resources: - - persistentvolumeclaims - verbs: - - get - - list - - watch - - apiGroups: - - '' - resources: - - services - verbs: - - get - - list - - create - - delete - - apiGroups: - - authorization.k8s.io - resources: - - subjectaccessreviews - - selfsubjectaccessreviews - verbs: - - create - # MLflow experiment tracking permissions (namespace-scoped CRDs) - # Required to grant MLflow access to session runner service accounts - # Sessions need these permissions to log experiments/runs to MLflow tracking server - # Uses Kubeflow MLflow Operator CRDs for Kubernetes-native RBAC authentication - - apiGroups: - - mlflow.kubeflow.org - resources: - - experiments - - runs - verbs: - - get - - list - - watch - - create - - update - - patch - - delete -- apiVersion: rbac.authorization.k8s.io/v1 - kind: ClusterRole - metadata: - labels: - rbac.authorization.k8s.io/aggregate-to-admin: 'true' - name: projectsettings-aggregate-to-admin - rules: - - apiGroups: - - vteam.ambient-code - resources: - - projectsettings - verbs: - - '*' - - apiGroups: - - vteam.ambient-code - resources: - - projectsettings/status - verbs: - - get - - update - - patch -- apiVersion: rbac.authorization.k8s.io/v1 - kind: ClusterRoleBinding - metadata: - name: agentic-operator - roleRef: - apiGroup: rbac.authorization.k8s.io - kind: ClusterRole - name: agentic-operator - subjects: - - kind: ServiceAccount - name: agentic-operator - namespace: ambient-code - - kind: ServiceAccount - name: agentic-operator - namespace: jsell-ambient-sso-poc -- apiVersion: rbac.authorization.k8s.io/v1 - kind: ClusterRoleBinding - metadata: - name: ambient-frontend-auth - roleRef: - apiGroup: rbac.authorization.k8s.io - kind: ClusterRole - name: ambient-frontend-auth - subjects: - - kind: ServiceAccount - name: frontend - namespace: ambient-code - - kind: ServiceAccount - name: frontend - namespace: jsell-ambient-sso-poc -- apiVersion: rbac.authorization.k8s.io/v1 - kind: ClusterRoleBinding - metadata: - name: ambient-users-can-list-projects - roleRef: - apiGroup: rbac.authorization.k8s.io - kind: ClusterRole - name: ambient-namespace-viewer - subjects: - - apiGroup: rbac.authorization.k8s.io - kind: Group - name: system:authenticated -- apiVersion: rbac.authorization.k8s.io/v1 - kind: ClusterRoleBinding - metadata: - name: backend-api - roleRef: - apiGroup: rbac.authorization.k8s.io - kind: ClusterRole - name: backend-api - subjects: - - kind: ServiceAccount - name: backend-api - namespace: ambient-code - - kind: ServiceAccount - name: backend-api - namespace: jsell-ambient-sso-poc -- apiVersion: v1 - data: - agent-registry.json: "[\n {\n \"id\": \"claude-agent-sdk\",\n \"displayName\": \"Claude Code\",\n \"description\": \"Anthropic Claude with full coding capabilities\",\n \"framework\": \"claude-agent-sdk\",\n \"provider\": \"anthropic\",\n \"container\": {\n \"image\": \"quay.io/ambient_code/vteam_claude_runner:latest\",\n \"port\": 8001,\n \"env\": {\n \"RUNNER_TYPE\": \"claude-agent-sdk\",\n \"RUNNER_STATE_DIR\": \".claude\"\n },\n \"resources\": {\n \"requests\": {\"cpu\": \"500m\", \"memory\": \"512Mi\"},\n \"limits\": {\"cpu\": \"2\", \"memory\": \"8Gi\"}\n }\n },\n \"sandbox\": {\n \"stateDir\": \".claude\",\n \"stateSyncImage\": \"quay.io/ambient_code/vteam_state_sync:latest\",\n \"persistence\": \"s3\",\n \"workspaceSize\": \"10Gi\",\n \"terminationGracePeriod\": 60,\n \"seed\": {\"cloneRepos\": true, \"hydrateState\": true}\n },\n \"auth\": {\n \"requiredSecretKeys\": [\"ANTHROPIC_API_KEY\"],\n \"secretKeyLogic\": \"any\",\n \"vertexSupported\": true\n },\n \"featureGate\": \"\"\n },\n {\n \"id\": \"gemini-cli\",\n \"displayName\": \"Gemini CLI\",\n \"description\": \"Google Gemini coding agent with built-in file, bash, and search tools\",\n \"framework\": \"gemini-cli\",\n \"provider\": \"google\",\n \"container\": {\n \"image\": \"quay.io/ambient_code/vteam_claude_runner:latest\",\n \"port\": 8001,\n \"env\": {\n \"RUNNER_TYPE\": \"gemini-cli\",\n \"RUNNER_STATE_DIR\": \".gemini\"\n }\n },\n \"sandbox\": {\n \"stateDir\": \".gemini\",\n \"stateSyncImage\": \"quay.io/ambient_code/vteam_state_sync:latest\",\n \"persistence\": \"s3\",\n \"workspaceSize\": \"10Gi\",\n \"terminationGracePeriod\": 60,\n \"seed\": {\"cloneRepos\": true, \"hydrateState\": true}\n },\n \"auth\": {\n \"requiredSecretKeys\": [\"GEMINI_API_KEY\", \"GOOGLE_API_KEY\"],\n \"secretKeyLogic\": \"any\",\n \"vertexSupported\": true\n },\n \"featureGate\": \"runner.gemini-cli.enabled\"\n }\n]\n" - kind: ConfigMap - metadata: - name: ambient-agent-registry - namespace: ambient-code -- apiVersion: v1 - data: - acl.yml: "- claim: email\n pattern: ^.*@(redhat\\.com|ambient\\.code)$\n" - jwks.json: '{"keys":[]} - - ' - kind: ConfigMap - metadata: - labels: - app: ambient-api-server - component: auth - name: ambient-api-server-auth - namespace: ambient-code -- apiVersion: v1 - data: - flags.json: "{\n \"flags\": [\n {\n \"name\": \"runner.gemini-cli.enabled\",\n \"description\": \"Enable Gemini CLI runner type for session creation\",\n \"tags\": [\n {\n \"type\": \"scope\",\n \"value\": \"workspace\"\n }\n ]\n },\n {\n \"name\": \"ldap.autocomplete.enabled\",\n \"description\": \"Enable LDAP user and group autocomplete for workspace sharing\",\n \"tags\": [\n {\n \"type\": \"scope\",\n \"value\": \"workspace\"\n }\n ]\n },\n {\n \"name\": \"scheduled-session.reuse.enabled\",\n \"description\": \"Enable reuse last session option for scheduled sessions\",\n \"tags\": [\n {\n \"type\": \"scope\",\n \"value\": \"workspace\"\n }\n ]\n },\n {\n \"name\": \"jira-write\",\n \"description\": \"Allow Jira MCP server to perform write operations in new sessions\",\n \"tags\": [\n {\n \"type\": \"scope\",\n \"value\": \"workspace\"\n }\n ]\n }\n ]\n}\n" - kind: ConfigMap - metadata: - name: ambient-flags - namespace: ambient-code -- apiVersion: v1 - data: - models.json: "{\n \"version\": 2,\n \"defaultModel\": \"claude-sonnet-4-5\",\n \"providerDefaults\": {\n \"anthropic\": \"claude-sonnet-4-5\",\n \"google\": \"gemini-2.5-flash\"\n },\n \"models\": [\n {\n \"id\": \"claude-sonnet-4-5\",\n \"label\": \"Claude Sonnet 4.5\",\n \"vertexId\": \"claude-sonnet-4-5@20250929\",\n \"provider\": \"anthropic\",\n \"available\": true,\n \"featureGated\": false\n },\n {\n \"id\": \"claude-opus-4-6\",\n \"label\": \"Claude Opus 4.6\",\n \"vertexId\": \"claude-opus-4-6@default\",\n \"provider\": \"anthropic\",\n \"available\": true,\n \"featureGated\": true\n },\n {\n \"id\": \"claude-opus-4-5\",\n \"label\": \"Claude Opus 4.5\",\n \"vertexId\": \"claude-opus-4-5@20251101\",\n \"provider\": \"anthropic\",\n \"available\": true,\n \"featureGated\": false\n },\n {\n \"id\": \"claude-haiku-4-5\",\n \"label\": \"Claude Haiku 4.5\",\n \"vertexId\": \"claude-haiku-4-5@20251001\",\n \"provider\": \"anthropic\",\n \"available\": true,\n \"featureGated\": false\n },\n {\n \"id\": \"claude-sonnet-4-6\",\n \"label\": \"Claude Sonnet 4.6\",\n \"vertexId\": \"claude-sonnet-4-6@default\",\n \"provider\": \"anthropic\",\n \"available\": true,\n \"featureGated\": true\n },\n {\n \"id\": \"gemini-2.5-flash\",\n \"label\": \"Gemini 2.5 Flash\",\n \"vertexId\": \"gemini-2.5-flash@default\",\n \"provider\": \"google\",\n \"available\": true,\n \"featureGated\": false\n },\n {\n \"id\": \"gemini-2.5-pro\",\n \"label\": \"Gemini 2.5 Pro\",\n \"vertexId\": \"gemini-2.5-pro@default\",\n \"provider\": \"google\",\n \"available\": true,\n \"featureGated\": true\n },\n {\n \"id\": \"gemini-2.5-flash-lite\",\n \"label\": \"Gemini 2.5 Flash Lite\",\n \"vertexId\": \"gemini-2.5-flash-lite@default\",\n \"provider\": \"google\",\n \"available\": true,\n \"featureGated\": true\n },\n {\n \"id\": \"gemini-2.5-flash-preview-04-17\",\n \"label\": \"Gemini 2.5 Flash Preview 04.17\",\n \"vertexId\": \"gemini-2.5-flash-preview-04-17@default\",\n \"provider\": \"google\",\n \"available\": false,\n \"featureGated\": true\n },\n {\n \"id\": \"gemini-3.1-flash-image-preview\",\n \"label\": \"Gemini 3.1 Flash Image Preview\",\n \"vertexId\": \"gemini-3.1-flash-image-preview@default\",\n \"provider\": \"google\",\n \"available\": false,\n \"featureGated\": true\n }\n ]\n}\n" - kind: ConfigMap - metadata: - name: ambient-models - namespace: ambient-code -- apiVersion: v1 - data: - ANTHROPIC_VERTEX_PROJECT_ID: ${ANTHROPIC_VERTEX_PROJECT_ID} - CLOUD_ML_REGION: global - GOOGLE_APPLICATION_CREDENTIALS: /app/vertex/itpc-gcp-hcm-pe-eng.json - USE_VERTEX: '1' - kind: ConfigMap - metadata: - labels: - app: agentic-operator - deployment-type: openshift - name: operator-config - namespace: ambient-code -- apiVersion: networking.k8s.io/v1 - kind: NetworkPolicy - metadata: - name: allow-from-runner-namespaces - namespace: ${NAMESPACE} - spec: - podSelector: - matchLabels: - app: backend-api - policyTypes: - - Ingress - ingress: - - from: - - namespaceSelector: {} - podSelector: - matchLabels: - app: ambient-code-runner -- apiVersion: apps/v1 - kind: Deployment - metadata: - labels: - app: agentic-operator - name: agentic-operator - namespace: ambient-code - spec: - replicas: 1 - selector: - matchLabels: - app: agentic-operator - template: - metadata: - labels: - app: agentic-operator - spec: - containers: - - args: - - --max-concurrent-reconciles=10 - - --health-probe-bind-address=:8081 - - --leader-elect=false - env: - - name: AMBIENT_CODE_RUNNER_IMAGE - value: ${IMAGE_AMBIENT_RUNNER}:${IMAGE_TAG} - - name: MAX_CONCURRENT_RECONCILES - value: '10' - - name: NAMESPACE - valueFrom: - fieldRef: - fieldPath: metadata.namespace - - name: BACKEND_NAMESPACE - valueFrom: - fieldRef: - fieldPath: metadata.namespace - - name: BACKEND_API_URL - value: http://backend-service:8080/api - - name: IMAGE_PULL_POLICY - value: IfNotPresent - - name: USE_VERTEX - valueFrom: - configMapKeyRef: - key: USE_VERTEX - name: operator-config - optional: true - - name: CLOUD_ML_REGION - valueFrom: - configMapKeyRef: - key: CLOUD_ML_REGION - name: operator-config - optional: true - - name: ANTHROPIC_VERTEX_PROJECT_ID - valueFrom: - configMapKeyRef: - key: ANTHROPIC_VERTEX_PROJECT_ID - name: operator-config - optional: true - - name: GOOGLE_APPLICATION_CREDENTIALS - valueFrom: - configMapKeyRef: - key: GOOGLE_APPLICATION_CREDENTIALS - name: operator-config - optional: true - - name: LANGFUSE_ENABLED - valueFrom: - secretKeyRef: - key: LANGFUSE_ENABLED - name: ambient-admin-langfuse-secret - optional: true - - name: LANGFUSE_HOST - valueFrom: - secretKeyRef: - key: LANGFUSE_HOST - name: ambient-admin-langfuse-secret - optional: true - - name: LANGFUSE_PUBLIC_KEY - valueFrom: - secretKeyRef: - key: LANGFUSE_PUBLIC_KEY - name: ambient-admin-langfuse-secret - optional: true - - name: LANGFUSE_SECRET_KEY - valueFrom: - secretKeyRef: - key: LANGFUSE_SECRET_KEY - name: ambient-admin-langfuse-secret - optional: true - - name: GOOGLE_OAUTH_CLIENT_ID - valueFrom: - secretKeyRef: - key: GOOGLE_OAUTH_CLIENT_ID - name: google-workflow-app-secret - optional: true - - name: GOOGLE_OAUTH_CLIENT_SECRET - valueFrom: - secretKeyRef: - key: GOOGLE_OAUTH_CLIENT_SECRET - name: google-workflow-app-secret - optional: true - - name: STATE_SYNC_IMAGE - value: quay.io/ambient_code/vteam_state_sync:latest - - name: S3_ENDPOINT - value: http://minio.ambient-code.svc:9000 - - name: S3_BUCKET - value: ambient-sessions - - name: DEPLOYMENT_ENV - value: production - - name: VERSION - value: latest - image: ${IMAGE_OPERATOR}:${IMAGE_TAG} - imagePullPolicy: Always - livenessProbe: - httpGet: - path: /healthz - port: health - initialDelaySeconds: 15 - periodSeconds: 20 - name: agentic-operator - ports: - - containerPort: 8081 - name: health - protocol: TCP - readinessProbe: - httpGet: - path: /readyz - port: health - initialDelaySeconds: 5 - periodSeconds: 10 - resources: - limits: - cpu: 2 - memory: 4Gi - requests: - cpu: 100m - memory: 512Mi - volumeMounts: - - mountPath: /config/models - name: model-manifest - readOnly: true - - mountPath: /config/registry - name: agent-registry - readOnly: true - restartPolicy: Always - serviceAccountName: agentic-operator - volumes: - - configMap: - name: ambient-models - optional: true - name: model-manifest - - configMap: - name: ambient-agent-registry - optional: true - name: agent-registry diff --git a/components/manifests/templates/template-services.yaml b/components/manifests/templates/template-services.yaml index 71581fc2a..ebfdd46f6 100644 --- a/components/manifests/templates/template-services.yaml +++ b/components/manifests/templates/template-services.yaml @@ -1,205 +1,146 @@ apiVersion: template.openshift.io/v1 kind: Template metadata: - name: ambient-code-services + name: ambient-code-platform annotations: - description: Ambient Code Platform - Services -parameters: -- name: IMAGE_TAG - description: Image tag - required: true -- name: IMAGE_BACKEND - value: quay.io/redhat-services-prod/hcm-eng-prod-tenant/ambient-code-main/ambient-code-backend-main -- name: IMAGE_FRONTEND - value: quay.io/redhat-services-prod/hcm-eng-prod-tenant/ambient-code-main/ambient-code-frontend-main -- name: IMAGE_PUBLIC_API - value: quay.io/redhat-services-prod/hcm-eng-prod-tenant/ambient-code-main/ambient-code-public-api-main -- name: IMAGE_AMBIENT_API_SERVER - value: quay.io/redhat-services-prod/hcm-eng-prod-tenant/ambient-code-main/ambient-code-ambient-api-server-main -- name: OAUTH_PROXY_IMAGE_NAME - value: registry.redhat.io/openshift4/ose-oauth-proxy-rhel9 -- name: OAUTH_PROXY_IMAGE_TAG - value: v4.18.0-202506230505.p0.gcbd44ad.assembly.stream.el9 -- name: NAMESPACE - value: ambient-code -- name: UPSTREAM_TIMEOUT - value: 5m + description: "Ambient Code Platform — API server, control plane, UI, and database" + tags: "ambient,ai,platform" objects: + +# --- ServiceAccounts --- + - apiVersion: v1 - kind: Namespace - metadata: - annotations: - app.kubernetes.io/name: ambient-code - app.kubernetes.io/part-of: ambient-code - labels: - app: vteam - name: ambient-code - name: ambient-code -- apiVersion: v1 - kind: Secret + kind: ServiceAccount metadata: - labels: - app: ambient-api-server - component: api name: ambient-api-server - namespace: ambient-code - stringData: - sentry.key: '' - type: Opaque -- apiVersion: v1 - kind: Service - metadata: - annotations: - description: Exposes the ambient-api-server REST API - service.beta.openshift.io/serving-cert-secret-name: ambient-api-server-tls + namespace: ${NAMESPACE} labels: app: ambient-api-server - component: api - name: ambient-api-server - namespace: ambient-code - spec: - ports: - - name: api - port: 8000 - protocol: TCP - targetPort: 8000 - - name: grpc - port: 9000 - protocol: TCP - targetPort: 9000 - - name: metrics - port: 4433 - protocol: TCP - targetPort: 4433 - - name: health - port: 4434 - protocol: TCP - targetPort: 4434 - selector: - app: ambient-api-server - component: api + - apiVersion: v1 - kind: Service + kind: ServiceAccount metadata: + name: ambient-control-plane + namespace: ${NAMESPACE} labels: - app: backend-api - name: backend-service - namespace: ambient-code - spec: - ports: - - name: http - port: 8080 - protocol: TCP - targetPort: http - selector: - app: backend-api - type: ClusterIP -- apiVersion: v1 - kind: Service + app: ambient-control-plane + +# --- Database --- + +- apiVersion: apps/v1 + kind: Deployment metadata: - annotations: - service.alpha.openshift.io/serving-cert-secret-name: frontend-proxy-tls + name: ambient-api-server-db + namespace: ${NAMESPACE} labels: - app: frontend - name: frontend-service - namespace: ambient-code + app: ambient-api-server + component: database spec: - ports: - - name: dashboard-ui - port: 8443 - protocol: TCP - targetPort: dashboard-ui - - name: http - port: 3000 - protocol: TCP - targetPort: http + replicas: 1 + strategy: + type: Recreate selector: - app: frontend - type: ClusterIP + matchLabels: + app: ambient-api-server + component: database + template: + metadata: + labels: + app: ambient-api-server + component: database + spec: + securityContext: + runAsNonRoot: true + seccompProfile: + type: RuntimeDefault + containers: + - name: postgresql + image: registry.redhat.io/rhel9/postgresql-16:latest + imagePullPolicy: IfNotPresent + ports: + - name: postgresql + containerPort: 5432 + protocol: TCP + env: + - name: POSTGRESQL_USER + valueFrom: + secretKeyRef: + name: ambient-api-server-db + key: db.user + - name: POSTGRESQL_PASSWORD + valueFrom: + secretKeyRef: + name: ambient-api-server-db + key: db.password + - name: POSTGRESQL_DATABASE + valueFrom: + secretKeyRef: + name: ambient-api-server-db + key: db.name + volumeMounts: + - name: data + mountPath: /var/lib/pgsql/data + subPath: pgdata + resources: + requests: + cpu: 100m + memory: 256Mi + limits: + cpu: 500m + memory: 512Mi + readinessProbe: + exec: + command: + - /bin/sh + - -c + - pg_isready -U "$POSTGRESQL_USER" + initialDelaySeconds: 10 + periodSeconds: 10 + livenessProbe: + exec: + command: + - /bin/sh + - -c + - pg_isready -U "$POSTGRESQL_USER" + initialDelaySeconds: 30 + periodSeconds: 30 + securityContext: + allowPrivilegeEscalation: false + capabilities: + drop: + - ALL + volumes: + - name: data + emptyDir: {} + - apiVersion: v1 kind: Service metadata: + name: ambient-api-server-db + namespace: ${NAMESPACE} labels: - app: public-api - name: public-api-service - namespace: ambient-code + app: ambient-api-server + component: database spec: - ports: - - name: http - port: 8081 - protocol: TCP - targetPort: http selector: - app: public-api - type: ClusterIP -- apiVersion: v1 - kind: LimitRange - metadata: - labels: - ambient-code.io/managed: 'true' - app.kubernetes.io/managed-by: ambient-code - name: ambient-default-limits - namespace: ambient-code - spec: - limits: - - default: - cpu: '2' - memory: 4Gi - defaultRequest: - cpu: 250m - memory: 256Mi - type: Container -- apiVersion: v1 - kind: PersistentVolumeClaim - metadata: - labels: app: ambient-api-server component: database - name: ambient-api-server-db-data - namespace: ambient-code - spec: - accessModes: - - ReadWriteOnce - resources: - requests: - storage: 1Gi -- apiVersion: v1 - kind: PersistentVolumeClaim - metadata: - labels: - app: backend-api - component: state-storage - name: backend-state-pvc - namespace: ambient-code - spec: - accessModes: - - ReadWriteOnce - resources: - requests: - storage: 5Gi -- apiVersion: v1 - kind: PersistentVolumeClaim - metadata: - labels: - app: postgresql - app.kubernetes.io/component: database - app.kubernetes.io/name: postgresql - name: postgresql-data - namespace: ambient-code - spec: - accessModes: - - ReadWriteOnce - resources: - requests: - storage: 10Gi + ports: + - name: postgresql + port: 5432 + targetPort: 5432 + protocol: TCP + +# --- API Server --- + - apiVersion: apps/v1 kind: Deployment metadata: + name: ambient-api-server + namespace: ${NAMESPACE} labels: app: ambient-api-server component: api - name: ambient-api-server - namespace: ambient-code spec: replicas: 1 selector: @@ -217,698 +158,523 @@ objects: app: ambient-api-server component: api spec: - containers: - - command: - - /usr/local/bin/ambient-api-server - - serve - - --db-host-file=/secrets/db/db.host - - --db-port-file=/secrets/db/db.port - - --db-user-file=/secrets/db/db.user - - --db-password-file=/secrets/db/db.password - - --db-name-file=/secrets/db/db.name - - --enable-jwt=true - - --enable-authz=false - - --jwk-cert-file=/configs/authentication/jwks.json - - --enable-https=false - - --api-server-bindaddress=:8000 - - --metrics-server-bindaddress=:4433 - - --health-check-server-bindaddress=:4434 - - --db-sslmode=require - - --db-max-open-connections=50 - - --enable-db-debug=false - - --enable-metrics-https=false - - --http-read-timeout=5s - - --http-write-timeout=30s - - --cors-allowed-origins=* - - --cors-allowed-headers=X-Ambient-Project - - --enable-grpc=true - - --grpc-server-bindaddress=:9000 - - --alsologtostderr - - -v=4 - env: - - name: AMBIENT_ENV - value: production - image: ${IMAGE_AMBIENT_API_SERVER}:${IMAGE_TAG} - imagePullPolicy: Always - livenessProbe: - httpGet: - path: /api/ambient - port: 8000 - scheme: HTTP - initialDelaySeconds: 15 - periodSeconds: 5 - name: api-server - ports: - - containerPort: 8000 - name: api - protocol: TCP - - containerPort: 4433 - name: metrics - protocol: TCP - - containerPort: 4434 - name: health - protocol: TCP - - containerPort: 9000 - name: grpc - protocol: TCP - readinessProbe: - httpGet: - httpHeaders: - - name: User-Agent - value: Probe - path: /healthcheck - port: 4434 - scheme: HTTP - initialDelaySeconds: 20 - periodSeconds: 10 - resources: - limits: - cpu: 1 - memory: 1Gi - requests: - cpu: 200m - memory: 512Mi - securityContext: - allowPrivilegeEscalation: false - capabilities: - drop: - - ALL - readOnlyRootFilesystem: false - volumeMounts: - - mountPath: /secrets/db - name: db-secrets - - mountPath: /secrets/service - name: app-secrets - - mountPath: /configs/authentication - name: auth-config - initContainers: - - command: - - /usr/local/bin/ambient-api-server - - migrate - - --db-host-file=/secrets/db/db.host - - --db-port-file=/secrets/db/db.port - - --db-user-file=/secrets/db/db.user - - --db-password-file=/secrets/db/db.password - - --db-name-file=/secrets/db/db.name - - --db-sslmode=require - - --alsologtostderr - - -v=4 - image: ${IMAGE_AMBIENT_API_SERVER}:${IMAGE_TAG} - imagePullPolicy: Always - name: migration - securityContext: - allowPrivilegeEscalation: false - capabilities: - drop: - - ALL - readOnlyRootFilesystem: false - volumeMounts: - - mountPath: /secrets/db - name: db-secrets serviceAccountName: ambient-api-server + securityContext: + runAsNonRoot: true + seccompProfile: + type: RuntimeDefault + initContainers: + - name: migration + image: ${IMAGE_AMBIENT_API_SERVER}:${IMAGE_TAG} + imagePullPolicy: Always + command: + - /usr/local/bin/ambient-api-server + - migrate + - --db-host-file=/secrets/db/db.host + - --db-port-file=/secrets/db/db.port + - --db-user-file=/secrets/db/db.user + - --db-password-file=/secrets/db/db.password + - --db-name-file=/secrets/db/db.name + - --db-sslmode=disable + - --alsologtostderr + - -v=4 + volumeMounts: + - name: db-secrets + mountPath: /secrets/db + resources: + requests: + cpu: 50m + memory: 128Mi + limits: + cpu: 500m + memory: 512Mi + securityContext: + allowPrivilegeEscalation: false + capabilities: + drop: + - ALL + containers: + - name: api-server + image: ${IMAGE_AMBIENT_API_SERVER}:${IMAGE_TAG} + imagePullPolicy: Always + env: + - name: AMBIENT_ENV + value: production + - name: AMBIENT_API_TOKEN + valueFrom: + secretKeyRef: + name: ambient-control-plane-token + key: token + - name: JWK_CERT_URL + value: "${KEYCLOAK_REALM_URL}/protocol/openid-connect/certs" + - name: CREDENTIAL_ENCRYPTION_KEYRING + valueFrom: + secretKeyRef: + name: credential-encryption-key + key: keyring + optional: true + - name: CREDENTIAL_ENCRYPTION_KEY_VERSION + valueFrom: + secretKeyRef: + name: credential-encryption-key + key: version + optional: true + - name: CREDENTIAL_ENCRYPTION_ALLOW_PLAINTEXT + value: "true" + command: + - /usr/local/bin/ambient-api-server + - serve + - --db-host-file=/secrets/db/db.host + - --db-port-file=/secrets/db/db.port + - --db-user-file=/secrets/db/db.user + - --db-password-file=/secrets/db/db.password + - --db-name-file=/secrets/db/db.name + - --enable-jwt=true + - --enable-authz=false + - --jwk-cert-file=/configs/authentication/jwks.json + - --enable-https=false + - --enable-grpc=true + - --grpc-enable-tls=false + - --api-server-bindaddress=:8000 + - --metrics-server-bindaddress=:4433 + - --health-check-server-bindaddress=:4434 + - --enable-health-check-https=false + - --db-sslmode=disable + - --db-max-open-connections=50 + - --enable-db-debug=false + - --enable-metrics-https=false + - --http-read-timeout=5s + - --http-write-timeout=30s + - --cors-allowed-origins=* + - --cors-allowed-headers=X-Ambient-Project + - --grpc-server-bindaddress=:9000 + - --alsologtostderr + - -v=10 + ports: + - name: api + containerPort: 8000 + protocol: TCP + - name: grpc + containerPort: 9000 + protocol: TCP + - name: metrics + containerPort: 4433 + protocol: TCP + - name: health + containerPort: 4434 + protocol: TCP + volumeMounts: + - name: db-secrets + mountPath: /secrets/db + - name: app-secrets + mountPath: /secrets/service + - name: auth-config + mountPath: /configs/authentication + resources: + requests: + cpu: 200m + memory: 512Mi + limits: + cpu: "1" + memory: 1Gi + livenessProbe: + httpGet: + path: /api/ambient + port: 8000 + scheme: HTTP + initialDelaySeconds: 15 + periodSeconds: 5 + readinessProbe: + httpGet: + path: /healthcheck + port: 4434 + scheme: HTTP + httpHeaders: + - name: User-Agent + value: Probe + initialDelaySeconds: 20 + periodSeconds: 10 + securityContext: + allowPrivilegeEscalation: false + capabilities: + drop: + - ALL volumes: - - name: db-secrets - secret: - secretName: ambient-code-rds - - name: app-secrets - secret: - secretName: ambient-api-server - - configMap: - name: ambient-api-server-auth - name: auth-config + - name: db-secrets + secret: + secretName: ambient-api-server-db + - name: app-secrets + secret: + secretName: ambient-api-server + - name: auth-config + configMap: + name: ambient-api-server-auth + +- apiVersion: v1 + kind: Service + metadata: + name: ambient-api-server + namespace: ${NAMESPACE} + labels: + app: ambient-api-server + component: api + spec: + selector: + app: ambient-api-server + component: api + ports: + - name: api + port: 8000 + targetPort: 8000 + protocol: TCP + - name: grpc + port: 9000 + targetPort: 9000 + protocol: TCP + - name: metrics + port: 4433 + targetPort: 4433 + protocol: TCP + - name: health + port: 4434 + targetPort: 4434 + protocol: TCP + +# --- Control Plane --- + - apiVersion: apps/v1 kind: Deployment metadata: + name: ambient-control-plane + namespace: ${NAMESPACE} labels: - app: backend-api - name: backend-api - namespace: ambient-code + app: ambient-control-plane spec: replicas: 1 selector: matchLabels: - app: backend-api - strategy: - type: Recreate + app: ambient-control-plane template: metadata: labels: - app: backend-api - role: backend + app: ambient-control-plane spec: + serviceAccountName: ambient-control-plane + securityContext: + runAsNonRoot: true + seccompProfile: + type: RuntimeDefault containers: - - env: - - name: NAMESPACE - valueFrom: - fieldRef: - fieldPath: metadata.namespace - - name: PORT - value: '8080' - - name: STATE_BASE_DIR - value: /workspace - - name: SPEC_KIT_REPO - value: ambient-code/spec-kit-rh - - name: SPEC_KIT_VERSION - value: main - - name: SPEC_KIT_TEMPLATE - value: spec-kit-template-claude-sh - - name: IMAGE_PULL_POLICY - valueFrom: - configMapKeyRef: - key: IMAGE_PULL_POLICY - name: operator-config - optional: true - - name: GITHUB_APP_ID - valueFrom: - secretKeyRef: - key: GITHUB_APP_ID - name: github-app-secret - optional: true - - name: GITHUB_PRIVATE_KEY - valueFrom: - secretKeyRef: - key: GITHUB_PRIVATE_KEY - name: github-app-secret - optional: true - - name: GITHUB_CLIENT_ID - valueFrom: - secretKeyRef: - key: GITHUB_CLIENT_ID - name: github-app-secret - optional: true - - name: GITHUB_CLIENT_SECRET - valueFrom: - secretKeyRef: - key: GITHUB_CLIENT_SECRET - name: github-app-secret - optional: true - - name: GITHUB_STATE_SECRET - valueFrom: - secretKeyRef: - key: GITHUB_STATE_SECRET - name: github-app-secret - optional: true - - name: GOOGLE_OAUTH_CLIENT_ID - valueFrom: - secretKeyRef: - key: GOOGLE_OAUTH_CLIENT_ID - name: google-workflow-app-secret - optional: true - - name: GOOGLE_OAUTH_CLIENT_SECRET - valueFrom: - secretKeyRef: - key: GOOGLE_OAUTH_CLIENT_SECRET - name: google-workflow-app-secret - optional: true - - name: OAUTH_STATE_SECRET - valueFrom: - secretKeyRef: - key: OAUTH_STATE_SECRET - name: google-workflow-app-secret - optional: true - - name: BACKEND_URL - valueFrom: - secretKeyRef: - key: BACKEND_URL - name: google-workflow-app-secret - optional: true - - name: OPERATOR_IMAGE - valueFrom: - configMapKeyRef: - key: OPERATOR_IMAGE - name: operator-config - optional: true - - name: OOTB_WORKFLOWS_REPO - value: https://github.com/ambient-code/workflows.git - - name: OOTB_WORKFLOWS_BRANCH - value: main - - name: OOTB_WORKFLOWS_PATH - value: workflows - - name: USE_VERTEX - valueFrom: - configMapKeyRef: - key: USE_VERTEX - name: operator-config - optional: true - - name: CLOUD_ML_REGION - valueFrom: - configMapKeyRef: - key: CLOUD_ML_REGION - name: operator-config - optional: true - - name: ANTHROPIC_VERTEX_PROJECT_ID - valueFrom: - configMapKeyRef: - key: ANTHROPIC_VERTEX_PROJECT_ID - name: operator-config - optional: true - - name: GOOGLE_APPLICATION_CREDENTIALS - valueFrom: - configMapKeyRef: - key: GOOGLE_APPLICATION_CREDENTIALS - name: operator-config - optional: true - - name: LDAP_SRV_DOMAIN - valueFrom: - configMapKeyRef: - key: LDAP_SRV_DOMAIN - name: ldap-config - optional: true - - name: LDAP_URL - valueFrom: - configMapKeyRef: - key: LDAP_URL - name: ldap-config - optional: true - - name: LDAP_BASE_DN - valueFrom: - configMapKeyRef: - key: LDAP_BASE_DN - name: ldap-config - optional: true - - name: LDAP_GROUP_BASE_DN - valueFrom: - configMapKeyRef: - key: LDAP_GROUP_BASE_DN - name: ldap-config - optional: true - - name: LDAP_BIND_DN - valueFrom: - configMapKeyRef: - key: LDAP_BIND_DN - name: ldap-config - optional: true - - name: LDAP_BIND_PASSWORD - valueFrom: - secretKeyRef: - key: LDAP_BIND_PASSWORD - name: ldap-credentials - optional: true - - name: LDAP_CA_CERT_PATH - valueFrom: - configMapKeyRef: - key: LDAP_CA_CERT_PATH - name: ldap-config - optional: true - - name: UNLEASH_URL - valueFrom: - secretKeyRef: - key: unleash-url - name: unleash-credentials - optional: true - - name: UNLEASH_CLIENT_KEY - valueFrom: - secretKeyRef: - key: client-api-token - name: unleash-credentials - optional: true - - name: UNLEASH_ADMIN_URL - valueFrom: - secretKeyRef: - key: unleash-admin-url - name: unleash-credentials - optional: true - - name: UNLEASH_ADMIN_TOKEN - valueFrom: - secretKeyRef: - key: admin-api-token - name: unleash-credentials - optional: true - - name: UNLEASH_PROJECT - valueFrom: - secretKeyRef: - key: unleash-project - name: unleash-credentials - optional: true - - name: UNLEASH_ENVIRONMENT - valueFrom: - secretKeyRef: - key: unleash-environment - name: unleash-credentials - optional: true - image: ${IMAGE_BACKEND}:${IMAGE_TAG} - imagePullPolicy: Always - livenessProbe: - httpGet: - path: /health - port: http - initialDelaySeconds: 30 - periodSeconds: 10 - name: backend-api - ports: - - containerPort: 8080 - name: http - readinessProbe: - httpGet: - path: /health - port: http - initialDelaySeconds: 5 - periodSeconds: 5 - resources: - limits: - cpu: '1' - memory: 1536Mi - requests: - cpu: 200m - memory: 512Mi - volumeMounts: - - mountPath: /workspace - name: backend-state - - mountPath: /app/vertex - name: vertex-credentials - readOnly: true - - mountPath: /config/models - name: model-manifest - readOnly: true - - mountPath: /config/flags - name: flags-config - readOnly: true - - mountPath: /config/registry - name: agent-registry - readOnly: true - - mountPath: /etc/pki/custom-ca - name: ldap-ca-cert - readOnly: true - serviceAccountName: backend-api + - name: control-plane + image: ${IMAGE_AMBIENT_CONTROL_PLANE}:${IMAGE_TAG} + imagePullPolicy: Always + env: + - name: MODE + value: kube + - name: PLATFORM_MODE + value: standard + - name: LOG_LEVEL + value: info + - name: AMBIENT_API_TOKEN + valueFrom: + secretKeyRef: + name: ambient-control-plane-token + key: token + - name: AMBIENT_API_SERVER_URL + value: "http://ambient-api-server.${NAMESPACE}.svc:8000" + - name: AMBIENT_GRPC_SERVER_ADDR + value: "ambient-api-server.${NAMESPACE}.svc:9000" + - name: AMBIENT_GRPC_USE_TLS + value: "false" + - name: MCP_API_SERVER_URL + value: "http://ambient-api-server.${NAMESPACE}.svc:8000" + - name: CP_TOKEN_URL + value: "http://ambient-control-plane.${NAMESPACE}.svc:8080/token" + - name: CP_RUNTIME_NAMESPACE + valueFrom: + fieldRef: + fieldPath: metadata.namespace + - name: RUNNER_IMAGE + value: "${IMAGE_AMBIENT_RUNNER}:${IMAGE_TAG}" + - name: MCP_IMAGE + value: "${IMAGE_AMBIENT_MCP}:${IMAGE_TAG}" + - name: GITHUB_MCP_IMAGE + value: "${IMAGE_CREDENTIAL_GITHUB}:${IMAGE_TAG}" + - name: JIRA_MCP_IMAGE + value: "${IMAGE_CREDENTIAL_JIRA}:${IMAGE_TAG}" + - name: K8S_MCP_IMAGE + value: "${IMAGE_CREDENTIAL_K8S}:${IMAGE_TAG}" + - name: GOOGLE_MCP_IMAGE + value: "${IMAGE_CREDENTIAL_GOOGLE}:${IMAGE_TAG}" + - name: USE_VERTEX + value: "1" + - name: ANTHROPIC_API_KEY + valueFrom: + secretKeyRef: + name: ambient-anthropic + key: ANTHROPIC_API_KEY + - name: ANTHROPIC_VERTEX_PROJECT_ID + value: ${ANTHROPIC_VERTEX_PROJECT_ID} + - name: CLOUD_ML_REGION + value: ${CLOUD_ML_REGION} + - name: GOOGLE_APPLICATION_CREDENTIALS + value: /app/vertex/itpc-gcp-hcm-pe-eng.json + - name: VERTEX_SECRET_NAME + value: ambient-vertex + - name: VERTEX_SECRET_NAMESPACE + value: ${NAMESPACE} + ports: + - name: token + containerPort: 8080 + protocol: TCP + volumeMounts: + - name: vertex-credentials + mountPath: /app/vertex + readOnly: true + resources: + requests: + cpu: 50m + memory: 64Mi + limits: + cpu: 200m + memory: 256Mi + securityContext: + readOnlyRootFilesystem: true + allowPrivilegeEscalation: false + capabilities: + drop: + - ALL volumes: - - name: backend-state - persistentVolumeClaim: - claimName: backend-state-pvc - - name: vertex-credentials - secret: - optional: true - secretName: stage-gcp-creds - - configMap: - name: ambient-models - optional: true - name: model-manifest - - configMap: - name: ambient-flags - optional: true - name: flags-config - - configMap: - name: ambient-agent-registry - optional: true - name: agent-registry - - configMap: - name: ldap-ca-cert - optional: true - name: ldap-ca-cert -- apiVersion: apps/v1 - kind: Deployment + - name: vertex-credentials + secret: + secretName: ambient-vertex + +- apiVersion: v1 + kind: Service metadata: + name: ambient-control-plane + namespace: ${NAMESPACE} labels: - app: frontend - name: frontend - namespace: ambient-code + app: ambient-control-plane spec: selector: - matchLabels: - app: frontend - template: - metadata: - labels: - app: frontend - spec: - containers: - - env: - - name: BACKEND_URL - value: http://backend-service:8080/api - - name: NODE_ENV - value: production - - name: GITHUB_APP_SLUG - value: ambient-code - - name: UNLEASH_URL - valueFrom: - secretKeyRef: - key: unleash-url - name: unleash-credentials - optional: true - - name: UNLEASH_CLIENT_KEY - valueFrom: - secretKeyRef: - key: client-api-token - name: unleash-credentials - optional: true - image: ${IMAGE_FRONTEND}:${IMAGE_TAG} - imagePullPolicy: Always - livenessProbe: - httpGet: - path: / - port: http - initialDelaySeconds: 30 - periodSeconds: 10 - name: frontend - ports: - - containerPort: 3000 - name: http - readinessProbe: - httpGet: - path: / - port: http - initialDelaySeconds: 5 - periodSeconds: 5 - resources: - limits: - cpu: 1000m - memory: 2Gi - requests: - cpu: 200m - memory: 512Mi - - args: - - --http-address=:8443 - - --https-address= - - --provider=openshift - - --client-id=ambient-code - - --client-secret-file=/etc/oauth-client/client_secret - - --upstream=http://localhost:3000 - - --tls-cert=/etc/tls/private/tls.crt - - --tls-key=/etc/tls/private/tls.key - - --cookie-secret-file=/etc/oauth-cookie/cookie_secret - - --cookie-expire=24h - - --cookie-refresh=1h - - --pass-access-token - - --scope=user:full - - --openshift-delegate-urls={"/":{"resource":"projects","verb":"list"}} - - --upstream-timeout=5m - - --skip-auth-regex=^/metrics - - --openshift-ca=/var/run/secrets/kubernetes.io/serviceaccount/ca.crt - image: ${OAUTH_PROXY_IMAGE_NAME}:${OAUTH_PROXY_IMAGE_TAG} - imagePullPolicy: IfNotPresent - livenessProbe: - failureThreshold: 3 - httpGet: - path: /oauth/healthz - port: dashboard-ui - scheme: HTTP - initialDelaySeconds: 10 - periodSeconds: 10 - successThreshold: 1 - timeoutSeconds: 1 - name: oauth-proxy - ports: - - containerPort: 8443 - name: dashboard-ui - readinessProbe: - failureThreshold: 3 - httpGet: - path: /oauth/healthz - port: dashboard-ui - scheme: HTTP - initialDelaySeconds: 10 - periodSeconds: 10 - successThreshold: 1 - timeoutSeconds: 1 - resources: - limits: - cpu: 200m - memory: 200Mi - requests: - cpu: 10m - memory: 50Mi - volumeMounts: - - mountPath: /etc/tls/private - name: frontend-proxy-tls - - mountPath: /etc/oauth-cookie - name: oauth-cookie-secret - - mountPath: /etc/oauth-client - name: oauth-client-secret - serviceAccountName: frontend - volumes: - - name: frontend-proxy-tls - secret: - secretName: frontend-proxy-tls - - name: oauth-cookie-secret - secret: - secretName: stage-cookie-secret - - name: oauth-client-secret - secret: - secretName: stage-sso-client + app: ambient-control-plane + ports: + - name: token + port: 8080 + targetPort: 8080 + protocol: TCP + +# --- UI --- + - apiVersion: apps/v1 kind: Deployment metadata: + name: ambient-ui + namespace: ${NAMESPACE} labels: - app: public-api - name: public-api - namespace: ambient-code + app: ambient-ui spec: replicas: 1 selector: matchLabels: - app: public-api + app: ambient-ui template: metadata: labels: - app: public-api - role: api-gateway + app: ambient-ui spec: + securityContext: + runAsNonRoot: true + seccompProfile: + type: RuntimeDefault containers: - - env: - - name: PORT - value: '8081' - - name: BACKEND_URL - value: http://backend-service:8080 - - name: GIN_MODE - value: release - - name: BACKEND_TIMEOUT - value: 30s - - name: RATE_LIMIT_RPS - value: '100' - - name: RATE_LIMIT_BURST - value: '200' - image: ${IMAGE_PUBLIC_API}:${IMAGE_TAG} - imagePullPolicy: Always - livenessProbe: - httpGet: - path: /health - port: http - initialDelaySeconds: 10 - periodSeconds: 10 - name: public-api - ports: - - containerPort: 8081 - name: http - readinessProbe: - httpGet: - path: /ready - port: http - initialDelaySeconds: 5 - periodSeconds: 5 - resources: - limits: - cpu: 200m - memory: 256Mi - requests: - cpu: 50m - memory: 128Mi - securityContext: - allowPrivilegeEscalation: false - capabilities: - drop: - - ALL - readOnlyRootFilesystem: true - runAsNonRoot: true - serviceAccountName: public-api -- apiVersion: policy/v1 - kind: PodDisruptionBudget + - name: ambient-ui + image: ${IMAGE_AMBIENT_UI}:${IMAGE_TAG} + imagePullPolicy: Always + env: + - name: NODE_ENV + value: production + - name: API_SERVER_URL + value: "http://ambient-api-server:8000" + - name: SSO_ISSUER_URL + valueFrom: + secretKeyRef: + name: sso-credentials + key: SSO_ISSUER_URL + - name: SSO_CLIENT_ID + valueFrom: + secretKeyRef: + name: sso-credentials + key: SSO_CLIENT_ID + - name: SSO_CLIENT_SECRET + valueFrom: + secretKeyRef: + name: sso-credentials + key: SSO_CLIENT_SECRET + - name: SESSION_SECRET + valueFrom: + secretKeyRef: + name: sso-credentials + key: SESSION_SECRET + - name: SSO_REDIRECT_URI + value: ${SSO_REDIRECT_URI} + - name: NEXT_PUBLIC_PREVIEW_ALLOWED_HOSTS + value: ${PREVIEW_ALLOWED_HOSTS} + ports: + - name: http + containerPort: 3000 + protocol: TCP + volumeMounts: + - name: next-cache + mountPath: /app/.next/cache + - name: tmp + mountPath: /tmp + resources: + requests: + cpu: 100m + memory: 256Mi + limits: + cpu: 500m + memory: 512Mi + livenessProbe: + httpGet: + path: /api/healthz + port: 3000 + scheme: HTTP + initialDelaySeconds: 10 + periodSeconds: 10 + readinessProbe: + httpGet: + path: /api/healthz + port: 3000 + scheme: HTTP + initialDelaySeconds: 5 + periodSeconds: 5 + securityContext: + readOnlyRootFilesystem: true + allowPrivilegeEscalation: false + capabilities: + drop: + - ALL + volumes: + - name: next-cache + emptyDir: {} + - name: tmp + emptyDir: {} + +- apiVersion: v1 + kind: Service metadata: + name: ambient-ui-service + namespace: ${NAMESPACE} labels: - app: public-api - name: public-api-pdb - namespace: ambient-code + app: ambient-ui spec: - minAvailable: 1 selector: - matchLabels: - app: public-api + app: ambient-ui + ports: + - name: http + port: 3000 + targetPort: 3000 + protocol: TCP + +# --- Routes --- + - apiVersion: route.openshift.io/v1 kind: Route metadata: - labels: - app: ambient-api-server - component: api name: ambient-api-server - namespace: ambient-code - spec: - port: - targetPort: api - tls: - insecureEdgeTerminationPolicy: Redirect - termination: reencrypt - to: - kind: Service - name: ambient-api-server -- apiVersion: route.openshift.io/v1 - kind: Route - metadata: + namespace: ${NAMESPACE} labels: app: ambient-api-server - component: grpc - name: ambient-api-server-grpc - namespace: ambient-code + annotations: + haproxy.router.openshift.io/timeout: 10m spec: - port: - targetPort: grpc - tls: - insecureEdgeTerminationPolicy: Redirect - termination: reencrypt + host: ${ROUTE_HOST_API} to: kind: Service name: ambient-api-server -- apiVersion: route.openshift.io/v1 - kind: Route - metadata: - labels: - app: backend-api - name: backend-route - namespace: ambient-code - spec: + weight: 100 port: - targetPort: http + targetPort: api tls: - insecureEdgeTerminationPolicy: Redirect termination: edge - to: - kind: Service - name: backend-service - weight: 100 - wildcardPolicy: None + insecureEdgeTerminationPolicy: Redirect + - apiVersion: route.openshift.io/v1 kind: Route metadata: - annotations: - haproxy.router.openshift.io/balance: roundrobin - haproxy.router.openshift.io/disable_cookies: 'true' + name: ambient-ui + namespace: ${NAMESPACE} labels: - app: frontend - name: frontend-route - namespace: ambient-code + app: ambient-ui spec: - port: - targetPort: dashboard-ui - tls: - insecureEdgeTerminationPolicy: Redirect - termination: edge + host: ${ROUTE_HOST_UI} to: kind: Service - name: frontend-service + name: ambient-ui-service weight: 100 - wildcardPolicy: None -- apiVersion: route.openshift.io/v1 - kind: Route - metadata: - labels: - app: public-api - name: public-api-route - namespace: ambient-code - spec: port: targetPort: http tls: - insecureEdgeTerminationPolicy: Redirect termination: edge - to: - kind: Service - name: public-api-service - weight: 100 - wildcardPolicy: None + insecureEdgeTerminationPolicy: Redirect + +# --- Parameters --- + +parameters: + - name: IMAGE_TAG + description: Image tag for all ambient components + required: true + - name: IMAGE_AMBIENT_API_SERVER + description: API server image + value: quay.io/ambient_code/vteam_api_server + - name: IMAGE_AMBIENT_CONTROL_PLANE + description: Control plane image + value: quay.io/ambient_code/vteam_control_plane + - name: IMAGE_AMBIENT_UI + description: UI image + value: quay.io/ambient_code/vteam_ambient_ui + - name: IMAGE_AMBIENT_RUNNER + description: Runner image (spawned by control plane) + value: quay.io/ambient_code/vteam_claude_runner + - name: IMAGE_AMBIENT_MCP + description: MCP proxy image + value: quay.io/ambient_code/vteam_mcp + - name: IMAGE_CREDENTIAL_GITHUB + description: GitHub credential sidecar image + value: quay.io/ambient_code/vteam_credential_github + - name: IMAGE_CREDENTIAL_JIRA + description: Jira credential sidecar image + value: quay.io/ambient_code/vteam_credential_jira + - name: IMAGE_CREDENTIAL_K8S + description: Kubernetes credential sidecar image + value: quay.io/ambient_code/vteam_credential_k8s + - name: IMAGE_CREDENTIAL_GOOGLE + description: Google credential sidecar image + value: quay.io/ambient_code/vteam_credential_google + - name: NAMESPACE + description: Target namespace + value: ambient-api + - name: KEYCLOAK_REALM_URL + description: Keycloak realm URL (e.g. https://keycloak.example.com/realms/ambient-code) + required: true + - name: ROUTE_HOST_API + description: API server route hostname + required: true + - name: ROUTE_HOST_UI + description: UI route hostname + required: true + - name: SSO_REDIRECT_URI + description: OIDC callback URL for ambient-ui + required: true + - name: ANTHROPIC_VERTEX_PROJECT_ID + description: GCP project ID for Vertex AI + value: itpc-gcp-hcm-pe-eng-claude + - name: CLOUD_ML_REGION + description: Vertex AI region + value: global + - name: PREVIEW_ALLOWED_HOSTS + description: Comma-separated host globs for ambient-ui preview + value: "*.openshiftapps.com" diff --git a/components/manifests/templates/validate.sh b/components/manifests/templates/validate.sh index 0f6bf2197..7ce306e95 100755 --- a/components/manifests/templates/validate.sh +++ b/components/manifests/templates/validate.sh @@ -7,9 +7,15 @@ echo "Validating OpenShift templates..." cd "$(dirname "$0")" -for template in template-operator.yaml template-services.yaml; do +for template in template-services.yaml; do echo " Checking $template..." - oc process -f "$template" --param=IMAGE_TAG=validation-test --local > /dev/null + oc process -f "$template" \ + --param=IMAGE_TAG=validation-test \ + --param=KEYCLOAK_REALM_URL=https://keycloak.example.com/realms/ambient-code \ + --param=ROUTE_HOST_API=api.example.com \ + --param=ROUTE_HOST_UI=ui.example.com \ + --param=SSO_REDIRECT_URI=https://ui.example.com/api/auth/sso/callback \ + --local > /dev/null echo " ✓ Valid" done