From d3ee714d5564a01baa0012f038a65851f45cb008 Mon Sep 17 00:00:00 2001 From: marcopiraccini Date: Fri, 10 Jul 2026 16:04:07 +0200 Subject: [PATCH 1/2] Remove managed mode Signed-off-by: marcopiraccini --- cli/deploy.js | 10 ++++----- lib/icc.js | 42 ++++++++--------------------------- profiles/development.yaml | 23 +++++++++++++++++++ profiles/skew-protection.yaml | 3 ++- 4 files changed, 38 insertions(+), 40 deletions(-) diff --git a/cli/deploy.js b/cli/deploy.js index 0bac3c0..0c9f657 100644 --- a/cli/deploy.js +++ b/cli/deploy.js @@ -122,10 +122,9 @@ export default async function cli (argv) { } } - // ICC-driven deploy: hand the image to ICC's deploy API and let the app's - // actuation mode decide (manage = ICC creates the workload; advise = ICC - // returns manifests that desk applies). This is the CI path a customer uses, - // and the way to exercise manage/advise modes end to end. + // ICC-driven deploy: hand the image to ICC's deploy API. ICC creates the + // workload (Deployment + Service) itself and the pod registers back. This is + // the CI path a customer uses -- the pipeline holds only a deploy token. if (args['via-icc']) { // --app-id is optional: with a deploy token ICC resolves the application from // the token (the CI needs only the token). Pass --app-id to force the @@ -148,8 +147,7 @@ export default async function cli (argv) { maxReplicas, env: Object.keys(envVars).length ? envVars : undefined }) - info(`ICC actuation mode: ${result.mode}`) - await handleIccDeploy(context, args.namespace, result, args['dry-run']) + handleIccDeploy(result) return } diff --git a/lib/icc.js b/lib/icc.js index 2dc1bcf..d1f61b3 100644 --- a/lib/icc.js +++ b/lib/icc.js @@ -1,11 +1,10 @@ import { addToRun } from './run-directory.js' -import { spawn, info, warn } from './utils.js' +import { info, warn } from './utils.js' // Drive a deploy through ICC's deploy API instead of templating + applying the -// workload directly. Lets you exercise the skew-protection actuation modes: -// manage -> ICC creates the Deployment + Service itself (nothing to apply here) -// advise -> ICC returns the manifests as a plan; desk applies them (below) -// observe -> ICC rejects the deploy API (you create workloads yourself) +// workload directly. ICC creates the Deployment + Service itself (the deploy API +// always applies); the pod then registers and the version goes active. The +// read-only manifests are available via /deploy/plan (getDeployPlan). // // Auth is a scoped deploy token (Bearer plt_deploy_...), the same CI path a // customer would use. icc.plt uses a local/self-signed cert, so TLS verification @@ -46,37 +45,14 @@ export async function deployViaIcc ({ iccUrl, appId, token, image, version, host } } -// Apply the manifests from an advise-mode plan via kubectl (the external actor's -// job). Each step's manifest is written to the run dir and applied. -export async function applyIccPlan (context, namespace, plan, dryRun) { - let applied = 0 - for (const step of plan) { - if (!step.manifest) continue - const name = step.manifest?.metadata?.name ?? `${step.kind ?? 'resource'}-${applied}` - info(` plan: ${step.kind}/${step.action} ${name}`) - if (step.command) info(` ${step.command}`) - if (dryRun) { applied++; continue } - const filePath = await addToRun(context.runDir, `icc-${step.kind}-${name}.json`, JSON.stringify(step.manifest)) - await spawn('kubectl', [`--namespace=${namespace}`, 'apply', `--filename=${filePath}`]) - applied++ - } - return applied -} - -// Report the outcome of an ICC deploy and, in advise mode, apply the plan. -export async function handleIccDeploy (context, namespace, result, dryRun) { +// Report the outcome of an ICC deploy. The deploy API always creates the +// workload, so the response is { deployed: true, controllerName, serviceName }. +export function handleIccDeploy (result) { if (result.deployed) { - info('\nManage mode: ICC created the Deployment + Service. Pods will register and the version will go active.') - return - } - const plan = result.plan ?? [] - if (result.pendingApply || plan.length > 0) { - info(`\nAdvise mode: ICC returned a ${plan.length}-step plan. Applying it now (external actor):`) - const applied = await applyIccPlan(context, namespace, plan, dryRun) - info(`\nApplied ${applied} manifest(s). ICC confirms the version active once pods register and the gateway route is Accepted.`) + info(`\nICC created the workload (${result.controllerName ?? 'Deployment'} + Service). The pod will register and the version will go active.`) return } - warn('ICC deploy returned no plan and deployed=false; nothing to do.') + warn('ICC deploy returned deployed=false; nothing to do.') } // Shared ICC request helper. icc.plt uses a local/self-signed cert, so TLS diff --git a/profiles/development.yaml b/profiles/development.yaml index c670fff..0c153d1 100644 --- a/profiles/development.yaml +++ b/profiles/development.yaml @@ -47,6 +47,18 @@ platformatic: enable: false ffc: enable: false + deployer: + enable: true # ICC creates workloads via the deploy API (grants create/patch on Deployments/Services/pull Secrets) + skew_protection: + enable: true + auto_cleanup: false # Keep expired Deployments/Services for inspection + http_grace_period_ms: 120000 # 2 min: keep >= traffic_window_ms + http_max_alive_ms: 900000 # 15 min for e2e testing + workflow_grace_period_ms: 300000 # 5 min for demo + workflow_max_alive_ms: 900000 # 15 min for demo + check_interval_ms: 10000 # 10 seconds + traffic_window_ms: 60000 # 1 min + cookie_max_age: 43200 # 12h in seconds (keep default) icc_jobs: enable: true @@ -81,3 +93,14 @@ platformatic: enable: false log_level: debug + + workflow: + hotReload: true + localRepo: "{{ WORKFLOW_REPO }}" + workingDir: /app/packages/workflow + + replicas: + min: 1 + max: 1 + + log_level: info diff --git a/profiles/skew-protection.yaml b/profiles/skew-protection.yaml index d2e2546..c27dc5a 100644 --- a/profiles/skew-protection.yaml +++ b/profiles/skew-protection.yaml @@ -45,9 +45,10 @@ platformatic: enable: false ffc: enable: false + deployer: + enable: true # ICC creates workloads via the deploy API (grants create/patch on Deployments/Services/pull Secrets) skew_protection: enable: true - manage_mode: true # Grant ICC create/patch on Deployments+Services so manage-mode deploys work (testing profile) auto_cleanup: false # Keep expired Deployments/Services for inspection http_grace_period_ms: 120000 # 2 min: keep >= traffic_window_ms http_max_alive_ms: 900000 # 15 min for e2e testing From 0dfac7d8ed9ab4562580fbf697d0ee735b9cc989 Mon Sep 17 00:00:00 2001 From: marcopiraccini Date: Fri, 10 Jul 2026 16:05:04 +0200 Subject: [PATCH 2/2] Remove managed mode Signed-off-by: marcopiraccini --- README.md | 31 ++++++++++++------------------- 1 file changed, 12 insertions(+), 19 deletions(-) diff --git a/README.md b/README.md index a370584..2cf738d 100644 --- a/README.md +++ b/README.md @@ -243,11 +243,10 @@ desk deploy --profile --dir ./my-watt-project --envfile ./my-watt-project #### Deploy through ICC's deploy API (`--via-icc`) -By default `desk` templates the Deployment + Service and applies them directly -(the skew-protection `observe` model: you create the workload, ICC manages -routing). Use `--via-icc` to instead drive the deploy through ICC's deploy API, -which lets you exercise the `advise` actuation mode (`manage` is temporarily -parked -- see the mode list below): +By default `desk` templates the Deployment + Service and applies them directly. +Use `--via-icc` to instead drive the deploy through ICC's deploy API: ICC creates +the Deployment + Service itself and the pod registers back (the CI path a customer +uses -- the pipeline holds only a deploy token): ```sh desk deploy --profile skew-protection --via-icc \ @@ -260,16 +259,10 @@ a CI needs only the token, image, and version, never the application UUID. Pass `--app-id ` to force the app-scoped route instead (e.g. when driving it with an admin cookie). -What happens depends on the app's mode (Settings → Skew Protection → Mode): - -* `manage` — **parked**: ICC returns `503 ManageModeUnavailable` while the - ICC-owned creation path is reworked; use `observe` or `advise`. (When restored: - ICC creates the Deployment + Service itself and `desk` applies nothing.) -* `advise` — ICC returns the manifests as a plan and `desk` applies them with - `kubectl` (use `--dry-run` to print the plan without applying). For a strictly - read-only workflow — fetch the plan, inspect it, and apply it yourself — use - [`get-plan`](#get-plan) instead; `--via-icc` is the one-shot that applies for you. -* `observe` — ICC rejects the deploy API (this is the default direct path above). +The deploy API always creates the workload; it does not gate on the app's +actuation mode (the mode now only governs version routing). For a strictly +read-only workflow -- fetch the manifests, inspect them, and apply them yourself +-- use [`get-plan`](#get-plan) instead. Flags: @@ -282,10 +275,10 @@ Flags: disabled for this call (local self-signed cert); for local testing only. `--via-icc` still builds/pushes the image when `--dir` is used; the image must -exist before ICC can reference it (`--image ` for a prebuilt one). (`manage` -mode, when restored, also requires the `plt-pod-manager` RBAC to create -Deployments/Services -- shipped in the helm chart; run `helm upgrade`.) See -`skew-protection/TESTING.md` for the full manual test walkthrough. +exist before ICC can reference it (`--image ` for a prebuilt one). ICC needs +the deployer RBAC to create Deployments/Services/pull Secrets -- gated behind +`services.icc.features.deployer.enable` in the helm chart (run `helm upgrade`). +See `skew-protection/TESTING.md` for the full manual test walkthrough. ### `get-plan`