← Google Cloud Dynamic Python Web AppExamplesLegal NoticePrivacy

StackToIT Migration Intelligence Workspace

FOR REVIEW — generated by StackToIT Assess. Architect review required before any decision.

Partially executable migration package · For review only · Not approved.

Technical details: run, versions, digest and evidence freshness

Assessment

Assessment
gcp-candidates/terraform-dynamic-python-webapp/infra (assessment format 0.24.0)
Assessment timestamp
Generated 2026-11-07 04:24 UTC by stacktoit 0.6.0-13076-ga19ea28c64 (a19ea28c64)
Run
6f8f72b2-1c34-4cfc-8483-344c41245364 · source digest sha256:19bfed642d5789ccada81b91d5c36e33175dcafd66dc46b1644ffa105d020000
Source snapshot
partly decided only at plan time · google not locked; google-beta not locked; http not locked; random not locked; time not locked
STACKIT target profile
Stable network model: the experimental STACKIT VPC resources are not used (STACKIT_STABLE)
STACKIT provider version
0.121.0
Knowledge base version
0.394.0
Evidence freshness
Not assessed — Evidence freshness as one measure is not assessed in this build. Dated evidence is shown where it is used: each STACKIT support option and each assurance row states when it was verified (verified_at, and recheck_after for support), in support_suitability and assurance. The date beside a readiness dimension is the assessment date, not a retrieval date.

Staleness: Not assessed — This build has no change detection, so there has been no re-check since the assessment was made (Generated 2026-11-07 04:24 UTC). The source may have changed since.

Source checks: Built-in source checks passed — OpenTofu validation of the source did not run (LOCK_FILE)

Run status: COMPLETE (report published). Source: partly decided only at plan time. Draft: GENERATED. The report was written whole; this is not a statement that the migration is ready.

Executive lens: the sections are in the order this reader usually wants, and Architecture and Engineering Evidence are put aside. Nothing is removed from the page: choose All to show every section in the order of the navigation, or follow a link into a section that is put aside.

Architect lens: the sections are in the order this reader usually wants, and Costs is put aside. Nothing is removed from the page: choose All to show every section in the order of the navigation, or follow a link into a section that is put aside.

Platform lens: the sections are in the order this reader usually wants, and Costs is put aside. Nothing is removed from the page: choose All to show every section in the order of the navigation, or follow a link into a section that is put aside.

Security lens: the sections are in the order this reader usually wants, and Costs and Migration Plan are put aside. Nothing is removed from the page: choose All to show every section in the order of the navigation, or follow a link into a section that is put aside.

Application owner lens: the sections are in the order this reader usually wants, and Engineering Evidence is put aside. Nothing is removed from the page: choose All to show every section in the order of the navigation, or follow a link into a section that is put aside.

Programme lens: the sections are in the order this reader usually wants, and Engineering Evidence is put aside. Nothing is removed from the page: choose All to show every section in the order of the navigation, or follow a link into a section that is put aside.

FinOps lens: the sections are in the order this reader usually wants, and Architecture and Engineering Evidence are put aside. Nothing is removed from the page: choose All to show every section in the order of the navigation, or follow a link into a section that is put aside.

Engineering lens: the sections are in the order this reader usually wants, and Costs is put aside. Nothing is removed from the page: choose All to show every section in the order of the navigation, or follow a link into a section that is put aside.

Work Board

Every job of the migration in one list, in four queues: who does it, what it waits for, what closes it and which file it carries out.

How the jobs are read from the plan, and the priorities, and the progress journal

Read from execution-plan.json and decisions.json: every record of the register that still asks something is a job, with the manual steps that stand for its question, and every other step of the plan is a job of its own (the OpenTofu steps of one file that wait for the same thing are one job). Steps defined: 78. Progress by kind of step: steps to answer: 24 · changes executable now: 5 · waiting: 47 (10 wait for a value); 2 refused (of 78 steps). 10 of the 12 automated steps (OpenTofu or a script) are free of decisions and manual prerequisites (2 require a design decision) · 0 can run as written · 10 of those 10 wait for a value (project_id, containers_machine_type, containers_nodes_max, containers_nodes_min and 7 more); a person can start 29 of the 64 manual steps now (10 wait for a manual prerequisite, 3 wait for an automated step, 22 require a design decision); 2 steps of the plan are permanently unsupported (refused). Every step of the plan is in exactly one job; 108 jobs hold them. Nothing here has been run or approved. migration/work-board.csv holds the same jobs.

Priority: First is the first required action and the manual work every automated step waits for, Holds steps a job some step of the plan waits for (or a refusal), Later the rest.

The jobs in the table are in board order: by queue, as the register and the plan list them (migration/work-board.csv has the same order). That is not the order to work in: Start here is, and stacktoit work next names the same first job.

No progress journal was given, so no job shows progress. Record what you carry out in progress-template.yaml (the run copies it to review/progress.yaml) and run the assessment again, or pass the file with --progress FILE.

Start here

First required action: Allow the calls of STACKIT APIs that are not generally available — Platform Architect. Allow STACKIT's pre-release APIs, which may change or be withdrawn: Pub/Sub v1beta (beta) and Secrets Manager v1 (release status not stated). 3 steps of the plan name this decision and wait for this answer (the steps that come after them are counted in what an answer frees); allowing the calls lets the plan carry them out and makes the migration depend on those APIs. If you say no (record a rejection), the calls are not made: the steps of Pub/Sub and Secrets Manager stay open. Record the answer in the decisions file given with --decisions (decisions-template.yaml); answer each API on its own through the members of the record.

stages of 12 automated steps: 12 in the draft, 10 free of decisions and manual prerequisites, 0 rest on no default to confirm, no opt-in to answer and no value to supply, 0 are approved (every decision and default confirmed in the decisions file, and no value left to supply)

78 of the 108 jobs can start now: they wait for no other job of this board, read from the order of the plan’s steps and the decisions they wait for. 30 jobs wait, each listed once below under the job it waits for last. Nothing has been run, so a job waits for every job it comes after. The number beside a job counts the jobs that wait for it, directly or through other jobs; the full title of a job is in the list below.

Provide information: 60 jobs can start

  1. Answer target.region INP-TSE-1eaf5b60fa62 · Customer Architect
  2. Answer source.google.region… INP-SPA-91ae2a413691 · Customer Architect
  3. Answer source.variable (enable_apis) INP-SPA-3cc45ef1d8a4 · Customer Architect
  4. Answer source.variable (init) INP-SPA-12276d55f145 · Customer Architect
  5. Answer source.variable (random_suffix) INP-SPA-dbe7ffc99d7e · Customer Architect
The other 55 jobs of this queue that can start

Approve a design: 9 jobs can start

  1. Choose how the data is moved · Data Architect · 13 jobs wait for it
  2. Allow the calls of STACKIT APIs that are not generally available · Platform Architect · 4 jobs wait for it
  3. Decide whether a proposed STACKIT alternative replaces a source capability · Platform Architect
  4. State where the units of each source project of the estate go · Platform Architect
  5. Map each source location of the estate to a STACKIT region · Platform Architect
The other 4 jobs of this queue that can start

Perform migration work: 9 jobs can start

  1. Apply the block of terraform/data.tf with OpenTofu TF/stackit_postgresflex_instance.postgres · Data Architect · 15 jobs wait for it
  2. Apply the block of terraform/storage.tf with OpenTofu TF/stackit_objectstorage_bucket.media · Storage Architect · 8 jobs wait for it
  3. Apply the blocks of terraform/security.tf with OpenTofu TF/stackit_secretsmanager_instance.migrated_secrets · Identity Architect · 4 jobs wait for it
  4. Apply the block of terraform/kubernetes.tf with OpenTofu TF/stackit_ske_cluster.containers · Platform Architect · 3 jobs wait for it
  5. Service account: manual review · Identity Architect
The other 4 jobs of this queue that can start
  • Service account: not drafted
  • Apply the blocks of terraform/identity.tf with OpenTofu TF/stackit_service_account.automation
  • Declare the topics and subscriptions of the source on the RabbitMQ instance… MAN/rabbitmq/topology
  • Apply the block of terraform/messaging.tf with OpenTofu TF/stackit_rabbitmq_instance.messaging

What these unblock

  • Apply the block of terraform/data.tf with OpenTofu TF/stackit_postgresflex_instance.postgres: 15 jobs wait for it, directly or through other jobs (1 directly); once it is done, 1 of them can start
    Which
    • Close what the plan lists as UNKNOWN, from the move host, with read-only queries. The move host… MAN/data/google_sql_database_instance.postgres/preflight
  • Choose how the data is moved: 13 jobs wait for it, directly or through other jobs (13 directly); none of them can start on this job alone
  • Apply the block of terraform/storage.tf with OpenTofu TF/stackit_objectstorage_bucket.media: 8 jobs wait for it, directly or through other jobs (1 directly); once it is done, 1 of them can start
    Which
    • Close what the plan lists as UNKNOWN, from the move host, before any object moves. The credentials… MAN/data/google_storage_bucket.media/preflight
  • Allow the calls of STACKIT APIs that are not generally available: 4 jobs wait for it, directly or through other jobs (4 directly); none of them can start on this job alone
  • Apply the blocks of terraform/security.tf with OpenTofu TF/stackit_secretsmanager_instance.migrated_secrets: 4 jobs wait for it, directly or through other jobs (2 directly); none of them can start on this job alone
  • Apply the block of terraform/kubernetes.tf with OpenTofu TF/stackit_ske_cluster.containers: 3 jobs wait for it, directly or through other jobs (3 directly); once it is done, 1 of them can start
    Which
    • Fetch the kubeconfig, check the health, create the namespace and the secrets of the SKE cluster(s)… MAN/draft/handover/cluster-access/kubeconfig-md

Waiting jobs, each under the job it waits for last

Waits for Allow the calls of STACKIT APIs that are not generally available (2 jobs)
  • Run the STACKIT API step WriteSecret of google_secret_manager_secret.django_admin_password API/secrets-manager-vault/WriteSecret/google_secret_manager_secret.django_admin_password — also waits for 1 other job
  • Run the STACKIT API step WriteSecret of google_secret_manager_secret.django_settings API/secrets-manager-vault/WriteSecret/google_secret_manager_secret.django_settings — also waits for 1 other job
Waits for Apply the block of terraform/storage.tf with OpenTofu TF/stackit_objectstorage_bucket.media (1 job)
  • Close what the plan lists as UNKNOWN, from the move host, before any object moves. The credentials… MAN/data/google_storage_bucket.media/preflight
Waits for Apply the block of terraform/data.tf with OpenTofu TF/stackit_postgresflex_instance.postgres (1 job)
  • Close what the plan lists as UNKNOWN, from the move host, with read-only queries. The move host… MAN/data/google_sql_database_instance.postgres/preflight
Waits for Apply the block of terraform/kubernetes.tf with OpenTofu TF/stackit_ske_cluster.containers (1 job)
  • Fetch the kubeconfig, check the health, create the namespace and the secrets of the SKE cluster(s)… MAN/draft/handover/cluster-access/kubeconfig-md
Waits for Fetch the kubeconfig, check the health, create the namespace and the secrets of the SKE cluster(s)… MAN/draft/handover/cluster-access/kubeconfig-md (2 jobs)
Waits for Run the STACKIT API step WriteSecret of google_secret_manager_secret.django_admin_password API/secrets-manager-vault/WriteSecret/google_secret_manager_secret.django_admin_password (1 job)
  • Read each migrated secret… MAN/path/secrets-migration/read-back — also waits for 2 other jobs
Waits for Close what the plan lists as UNKNOWN, from the move host, before any object moves. The credentials… MAN/data/google_storage_bucket.media/preflight (1 job)
  • Rehearse the copy with a representative part of the bucket… MAN/data/google_storage_bucket.media/rehearsal
Waits for Close what the plan lists as UNKNOWN, from the move host, with read-only queries. The move host… MAN/data/google_sql_database_instance.postgres/preflight (1 job)
  • Rehearse the chosen method into a scratch database of the target… MAN/data/google_sql_database_instance.postgres/rehearsal
Waits for Rehearse the chosen method into a scratch database of the target… MAN/data/google_sql_database_instance.postgres/rehearsal (3 jobs)
  • Source: turn logical decoding on: set the flag cloudsql.logical_decoding to on on the instance… MAN/data/google_sql_database_instance.postgres/initial-copy/logical-replication — also waits for 1 other job
  • List who writes (SELECT usename, application_name, client_addr, count(*) FROM pg_stat_activity WHERE datname = '<source-db>' GROUP BY 1, 2, 3 ORDER BY 4 DESC;) and record the connection settings of every client where they can be restored from. Then stop the writers at the application (services, jobs, migrations, cron). Do not make the source read-only and do not change it. Check: SELECT count(*) FROM pg_stat_activity WHERE datname = '<source-db>' AND state <> 'idle' AND pid <> pg_backend_pid(); is 0. Runbook section: terraform/handover/database-postgres/data-move.md#write-freeze-dump-restore. MAN/data/google_sql_database_instance.postgres/write-freeze/dump-restore — also waits for 1 other job
  • List who writes (SELECT usename, application_name, client_addr, count(*) FROM pg_stat_activity WHERE datname = '<source-db>' GROUP BY 1, 2, 3 ORDER BY 4 DESC;) and record the connection settings of every client where they can be restored from. Then stop the writers at the application (services, jobs, migrations, cron). Do not make the source read-only and do not change it. Check: SELECT count(*) FROM pg_stat_activity WHERE datname = '<source-db>' AND state <> 'idle' AND pid <> pg_backend_pid(); is 0. Runbook section: terraform/handover/database-postgres/data-move.md#write-freeze-own-tool. MAN/data/google_sql_database_instance.postgres/write-freeze/own-tool — also waits for 1 other job
Waits for Read each migrated secret… MAN/path/secrets-migration/read-back (1 job)
  • Remove the migration user stackit_secretsmanager_user.migration of the Secrets Manager instance… MAN/path/secrets-migration/retire-user — also waits for 1 other job
Waits for Rehearse the copy with a representative part of the bucket… MAN/data/google_storage_bucket.media/rehearsal (1 job)
  • While the writers keep writing to the source, copy every live object to the target. The credentials… MAN/data/google_storage_bucket.media/initial-copy/rclone-copy
Waits for While the writers keep writing to the source, copy every live object to the target. The credentials… MAN/data/google_storage_bucket.media/initial-copy/rclone-copy (1 job)
  • Run the same rclone copy again, as often as the business needs the target to be close to the… MAN/data/google_storage_bucket.media/delta-sync/rclone-copy
Waits for Source: turn logical decoding on: set the flag cloudsql.logical_decoding to on on the instance… MAN/data/google_sql_database_instance.postgres/initial-copy/logical-replication (1 job)
  • Keep the target apart: the application does not write to it and no DDL runs on either side. Watch… MAN/data/google_sql_database_instance.postgres/delta-sync/logical-replication — also waits for 1 other job
Waits for List who writes (SELECT usename, application_name, client_addr, count(*) FROM pg_stat_activity WHERE datname = '<source-db>' GROUP BY 1, 2, 3 ORDER BY 4 DESC;) and record the connection settings of every client where they can be restored from. Then stop the writers at the application (services, jobs, migrations, cron). Do not make the source read-only and do not change it. Check: SELECT count(*) FROM pg_stat_activity WHERE datname = '<source-db>' AND state <> 'idle' AND pid <> pg_backend_pid(); is 0. Runbook section: terraform/handover/database-postgres/data-move.md#write-freeze-dump-restore. MAN/data/google_sql_database_instance.postgres/write-freeze/dump-restore (1 job)
  • Dump inside the freeze: PGPASSWORD="$SOURCE_PGPASSWORD" PGSSLMODE=require pg_dump --host=<source-host> --port=<source-port> --username=<source-user> --dbname=<source-db> --format=directory --jobs=4 --no-owner --no-acl --file=<dump-dir> (Google's page names --no-owner and --no-acl for a dump of one database and the directory format for a parallel dump; dump one database at a time, since pg_dumpall fails for databases with several owners). Restore as the database owner into the empty database: PGPASSWORD="$TARGET_PGPASSWORD" PGSSLMODE=require pg_restore --host=<target-host> --port=<target-port> --username=<target-user> --dbname=<target-db> --jobs=4 --no-owner --no-acl <dump-dir> 2> restore.log, then read restore.log line by line; create the extensions of the source that the target lists and settle the ones it does not. Runbook section: terraform/handover/database-postgres/data-move.md#final-sync-dump-restore. MAN/data/google_sql_database_instance.postgres/final-sync/dump-restore — also waits for 1 other job
Waits for List who writes (SELECT usename, application_name, client_addr, count(*) FROM pg_stat_activity WHERE datname = '<source-db>' GROUP BY 1, 2, 3 ORDER BY 4 DESC;) and record the connection settings of every client where they can be restored from. Then stop the writers at the application (services, jobs, migrations, cron). Do not make the source read-only and do not change it. Check: SELECT count(*) FROM pg_stat_activity WHERE datname = '<source-db>' AND state <> 'idle' AND pid <> pg_backend_pid(); is 0. Runbook section: terraform/handover/database-postgres/data-move.md#write-freeze-own-tool. MAN/data/google_sql_database_instance.postgres/write-freeze/own-tool (1 job)
  • Copy the data of google_sql_database_instance.postgres to stackit_postgresflex_instance.postgres… MAN/data/google_sql_database_instance.postgres/final-sync/own-tool — also waits for 1 other job
Waits for Run the same rclone copy again, as often as the business needs the target to be close to the… MAN/data/google_storage_bucket.media/delta-sync/rclone-copy (1 job)
  • List who writes to the bucket… MAN/data/google_storage_bucket.media/write-freeze/rclone-copy
Waits for Keep the target apart: the application does not write to it and no DDL runs on either side. Watch… MAN/data/google_sql_database_instance.postgres/delta-sync/logical-replication (1 job)
  • List who writes (SELECT usename, application_name, client_addr, count(*) FROM pg_stat_activity WHERE datname = '<source-db>' GROUP BY 1, 2, 3 ORDER BY 4 DESC;) and record the connection settings of every client where they can be restored from. Then stop the writers at the application (services, jobs, migrations, cron). Do not make the source read-only and do not change it. Check: SELECT count(*) FROM pg_stat_activity WHERE datname = '<source-db>' AND state <> 'idle' AND pid <> pg_backend_pid(); is 0. Runbook section: terraform/handover/database-postgres/data-move.md#write-freeze-logical-replication. MAN/data/google_sql_database_instance.postgres/write-freeze/logical-replication — also waits for 1 other job
Waits for Dump inside the freeze: PGPASSWORD="$SOURCE_PGPASSWORD" PGSSLMODE=require pg_dump --host=<source-host> --port=<source-port> --username=<source-user> --dbname=<source-db> --format=directory --jobs=4 --no-owner --no-acl --file=<dump-dir> (Google's page names --no-owner and --no-acl for a dump of one database and the directory format for a parallel dump; dump one database at a time, since pg_dumpall fails for databases with several owners). Restore as the database owner into the empty database: PGPASSWORD="$TARGET_PGPASSWORD" PGSSLMODE=require pg_restore --host=<target-host> --port=<target-port> --username=<target-user> --dbname=<target-db> --jobs=4 --no-owner --no-acl <dump-dir> 2> restore.log, then read restore.log line by line; create the extensions of the source that the target lists and settle the ones it does not. Runbook section: terraform/handover/database-postgres/data-move.md#final-sync-dump-restore. MAN/data/google_sql_database_instance.postgres/final-sync/dump-restore (1 job)
  • Both sides, with the writers stopped… MAN/data/google_sql_database_instance.postgres/reconcile/dump-restore — also waits for 1 other job
Waits for Copy the data of google_sql_database_instance.postgres to stackit_postgresflex_instance.postgres… MAN/data/google_sql_database_instance.postgres/final-sync/own-tool (1 job)
  • Both sides, with the writers stopped… MAN/data/google_sql_database_instance.postgres/reconcile/own-tool — also waits for 1 other job
Waits for Both sides, with the writers stopped… MAN/data/google_sql_database_instance.postgres/reconcile/dump-restore (1 job)
  • Only after the target has run in production for the period the customer decides and the way back is… MAN/data/google_sql_database_instance.postgres/cleanup/dump-restore — also waits for 1 other job
Waits for List who writes (SELECT usename, application_name, client_addr, count(*) FROM pg_stat_activity WHERE datname = '<source-db>' GROUP BY 1, 2, 3 ORDER BY 4 DESC;) and record the connection settings of every client where they can be restored from. Then stop the writers at the application (services, jobs, migrations, cron). Do not make the source read-only and do not change it. Check: SELECT count(*) FROM pg_stat_activity WHERE datname = '<source-db>' AND state <> 'idle' AND pid <> pg_backend_pid(); is 0. Runbook section: terraform/handover/database-postgres/data-move.md#write-freeze-logical-replication. MAN/data/google_sql_database_instance.postgres/write-freeze/logical-replication (1 job)
  • Wait until the lag is 0. Copy the sequences… MAN/data/google_sql_database_instance.postgres/final-sync/logical-replication — also waits for 1 other job
Waits for List who writes to the bucket… MAN/data/google_storage_bucket.media/write-freeze/rclone-copy (1 job)
  • Inside the freeze run the rclone copy of the initial copy once more and read how many objects it… MAN/data/google_storage_bucket.media/final-sync/rclone-copy
Waits for Wait until the lag is 0. Copy the sequences… MAN/data/google_sql_database_instance.postgres/final-sync/logical-replication (1 job)
  • Both sides, with the writers stopped… MAN/data/google_sql_database_instance.postgres/reconcile/logical-replication — also waits for 1 other job
Waits for Inside the freeze run the rclone copy of the initial copy once more and read how many objects it… MAN/data/google_storage_bucket.media/final-sync/rclone-copy (1 job)
  • Both sides, with the writers stopped… MAN/data/google_storage_bucket.media/reconcile/rclone-copy
Waits for Both sides, with the writers stopped… MAN/data/google_sql_database_instance.postgres/reconcile/logical-replication (1 job)
  • Only after the target has run in production for the period the customer decides and the way back is… MAN/data/google_sql_database_instance.postgres/cleanup/logical-replication — also waits for 1 other job
Waits for Both sides, with the writers stopped… MAN/data/google_storage_bucket.media/reconcile/rclone-copy (1 job)
  • Only after the target has run in production for the period the customer decides and the way back is… MAN/data/google_storage_bucket.media/cleanup/rclone-copy

Assign an owner (2 jobs)

Nobody is named to carry these jobs out: no role follows from the plan for them, nor from the area of their units (a role is derived only when every unit of a job is in the one area the owner table knows: network, identity, data, storage, platform). Assign an owner to each in your own tracking before the work starts; each stays in its queue below, with the owner “Owner assignment required”. StackToIT reads no assignment: the board changes only when the plan states a role, and a run with every job assigned lists no such section.

Every job, by queue

Provide information (60 jobs)

JobOwnerPriorityBlocked byCloses whenEvidenceGenerated file
Answer target.region INP-TSE-1eaf5b60fa62
State: not answered
Customer ArchitectHolds steps — The request is answered in review/inputs.yaml (stacktoit work answer) and the assessment is run again.
Needs: The STACKIT region the migrated estate is built in.
Then: No other job on the board waits for it.
— review/inputs.yaml
Answer source.dataset.bandwidth (google_sql_database_instance.postgres) INP-SDE-2a7f7b5269a1
State: not answered
Application OwnerLater — The request is answered in review/inputs.yaml (stacktoit work answer) and the assessment is run again.
Needs: The network bandwidth available for moving the data of google_sql_database_instance.postgres: it sets the lower bound of the transfer time and decides whether a replication can catch up with the writes.
Then: No other job on the board waits for it.
— review/inputs.yaml
Answer source.dataset.bandwidth (google_storage_bucket.media) INP-SDE-e46eb1c97548
State: not answered
Application OwnerLater — The request is answered in review/inputs.yaml (stacktoit work answer) and the assessment is run again.
Needs: The network bandwidth available for moving the data of google_storage_bucket.media: it sets the lower bound of the transfer time and decides whether a replication can catch up with the writes.
Then: No other job on the board waits for it.
— review/inputs.yaml
Answer source.dataset.downtime (google_sql_database_instance.postgres) INP-SDE-281da2c43709
State: not answered
Application OwnerLater — The request is answered in review/inputs.yaml (stacktoit work answer) and the assessment is run again.
Needs: The downtime window a person accepts for the cutover of google_sql_database_instance.postgres: it is the window the transfer lower bound is held against: a lower bound above it makes the dump-and-restore method need a design.
Then: No other job on the board waits for it.
— review/inputs.yaml
Answer source.dataset.downtime (google_storage_bucket.media) INP-SDE-edc3995fc80b
State: not answered
Application OwnerLater — The request is answered in review/inputs.yaml (stacktoit work answer) and the assessment is run again.
Needs: The downtime window a person accepts for the cutover of google_storage_bucket.media: it is the window the transfer lower bound is held against: a lower bound above it makes the dump-and-restore method need a design.
Then: No other job on the board waits for it.
— review/inputs.yaml
Answer source.dataset.rpo (google_sql_database_instance.postgres) INP-SDE-711698e4152d
State: not answered
Application OwnerLater — The request is answered in review/inputs.yaml (stacktoit work answer) and the assessment is run again.
Needs: The recovery point objective (the data a person accepts to lose, as time) of google_sql_database_instance.postgres: it is recorded next to the data asset and shown in the plan of its move; the plan does not compute with it yet.
Then: No other job on the board waits for it.
— review/inputs.yaml
Answer source.dataset.rpo (google_storage_bucket.media) INP-SDE-09450a7fa213
State: not answered
Application OwnerLater — The request is answered in review/inputs.yaml (stacktoit work answer) and the assessment is run again.
Needs: The recovery point objective (the data a person accepts to lose, as time) of google_storage_bucket.media: it is recorded next to the data asset and shown in the plan of its move; the plan does not compute with it yet.
Then: No other job on the board waits for it.
— review/inputs.yaml
Answer source.dataset.rto (google_sql_database_instance.postgres) INP-SDE-d20a37a1a474
State: not answered
Application OwnerLater — The request is answered in review/inputs.yaml (stacktoit work answer) and the assessment is run again.
Needs: The recovery time objective (the time a person accepts the asset to be unavailable after a failure) of google_sql_database_instance.postgres: it is recorded next to the data asset and shown in the plan of its move; the plan does not compute with it yet.
Then: No other job on the board waits for it.
— review/inputs.yaml
Answer source.dataset.rto (google_storage_bucket.media) INP-SDE-9587eb7e8e9f
State: not answered
Application OwnerLater — The request is answered in review/inputs.yaml (stacktoit work answer) and the assessment is run again.
Needs: The recovery time objective (the time a person accepts the asset to be unavailable after a failure) of google_storage_bucket.media: it is recorded next to the data asset and shown in the plan of its move; the plan does not compute with it yet.
Then: No other job on the board waits for it.
— review/inputs.yaml
Answer source.dataset.size (google_sql_database_instance.postgres) INP-SDE-3475bcd86a5e
State: not answered
Application OwnerLater — The request is answered in review/inputs.yaml (stacktoit work answer) and the assessment is run again.
Needs: The size of the data of google_sql_database_instance.postgres: it sets the lower bound of the transfer time of the first copy (the size of the data, not the capacity the source provisions).
Then: No other job on the board waits for it.
— review/inputs.yaml
Answer source.dataset.size (google_storage_bucket.media) INP-SDE-039e4543956e
State: not answered
Application OwnerLater — The request is answered in review/inputs.yaml (stacktoit work answer) and the assessment is run again.
Needs: The size of the data of google_storage_bucket.media: it sets the lower bound of the transfer time of the first copy (the size of the data, not the capacity the source provisions).
Then: No other job on the board waits for it.
— review/inputs.yaml
Answer source.dataset.write_rate (google_sql_database_instance.postgres) INP-SDE-0df31f6e861f
State: not answered
Application OwnerLater — The request is answered in review/inputs.yaml (stacktoit work answer) and the assessment is run again.
Needs: The rate at which the data is written of google_sql_database_instance.postgres: it decides whether a replication can catch up with the writes and how long the freeze waits for the lag to reach zero.
Then: No other job on the board waits for it.
— review/inputs.yaml
Answer source.dataset.write_rate (google_storage_bucket.media) INP-SDE-13232ceea041
State: not answered
Application OwnerLater — The request is answered in review/inputs.yaml (stacktoit work answer) and the assessment is run again.
Needs: The rate at which the data is written of google_storage_bucket.media: it decides whether a replication can catch up with the writes and how long the freeze waits for the lag to reach zero.
Then: No other job on the board waits for it.
— review/inputs.yaml
Answer source.google.region (google) INP-SPA-91ae2a413691
State: not answered
Customer ArchitectHolds steps — The request is answered in review/inputs.yaml (stacktoit work answer) and the assessment is run again.
Needs: The Google Cloud region the provider configuration google runs in. The source reads the region of the google provider configuration google from a variable's default (us-central1), which -var or TF_VAR_* can override. Until you answer, the region is read as us-central1 and no zone default is written from it.
Then: No other job on the board waits for it.
— review/inputs.yaml
Answer source.variable (enable_apis) INP-SPA-3cc45ef1d8a4
State: not answered
Customer ArchitectHolds steps — The request is answered in review/inputs.yaml (stacktoit work answer) and the assessment is run again.
Needs: The value the running environment gives the root variable enable_apis, which the source sets only as a default that a variable file or the command line can override.
Then: No other job on the board waits for it.
— review/inputs.yaml
Answer source.variable (init) INP-SPA-12276d55f145
State: not answered
Customer ArchitectHolds steps — The request is answered in review/inputs.yaml (stacktoit work answer) and the assessment is run again.
Needs: The value the running environment gives the root variable init, which the source sets only as a default that a variable file or the command line can override.
Then: No other job on the board waits for it.
— review/inputs.yaml
Answer source.variable (random_suffix) INP-SPA-dbe7ffc99d7e
State: not answered
Customer ArchitectHolds steps — The request is answered in review/inputs.yaml (stacktoit work answer) and the assessment is run again.
Needs: The value the running environment gives the root variable random_suffix, which the source sets only as a default that a variable file or the command line can override.
Then: No other job on the board waits for it.
— review/inputs.yaml
Answer target.project.source_project (example-project) INP-TSE-e0f55f8e074c
State: not answered
Customer ArchitectLater — The request is answered in review/inputs.yaml (stacktoit work answer) and the assessment is run again.
Needs: Where the units of the project example-project go on STACKIT: 1 unit(s) of the estate stand in it.
Then: No other job on the board waits for it.
— review/inputs.yaml
Answer target.project.source_project (unread) INP-TSE-f058614b497f
State: not answered
Customer ArchitectLater — The request is answered in review/inputs.yaml (stacktoit work answer) and the assessment is run again.
Needs: Where the units of a project the scan cannot read (the value comes from an input a plan can change, or the provider block states it) go on STACKIT: 3 unit(s) of the estate stand in it.
Then: No other job on the board waits for it.
— review/inputs.yaml
Answer target.region.source_location (unread) INP-TSE-ed9be9064ccf
State: not answered
Customer ArchitectLater — The request is answered in review/inputs.yaml (stacktoit work answer) and the assessment is run again.
Needs: The STACKIT region that holds the residency of a location the scan cannot read (the value comes from an input a plan can change, or the source does not state it), which 4 unit(s) of the estate stand in.
Then: No other job on the board waits for it.
— review/inputs.yaml
Answer target.secret_store.binding INP-TSE-7a8d984b0e4d
State: not answered
Customer ArchitectLater — The request is answered in review/inputs.yaml (stacktoit work answer) and the assessment is run again.
Needs: Who owns the STACKIT Secrets Manager instance that replaces every migrated secret (2 source units): the draft creates it (the DEFAULT), or an existing secret store is read, bound by a person, or refused. The identifier of an existing secret store is yours to give.
Then: No other job on the board waits for it.
— review/inputs.yaml
Answer target.workload.identity (google_cloud_run_v2_job.migrate) INP-TSE-2a2e667de9c2
State: not answered
Customer ArchitectHolds steps — The request is answered in review/inputs.yaml (stacktoit work answer) and the assessment is run again.
Needs: Which identity the pods of google_cloud_run_v2_job.migrate use on STACKIT. The source runs them as the Google service account google_service_account.automation; a pod on STACKIT has no Google identity, and there is no default model.
Then: No other job on the board waits for it.
— review/inputs.yaml
Answer target.workload.identity (google_cloud_run_v2_service.server) INP-TSE-77b8285fa505
State: not answered
Customer ArchitectHolds steps — The request is answered in review/inputs.yaml (stacktoit work answer) and the assessment is run again.
Needs: Which identity the pods of google_cloud_run_v2_service.server use on STACKIT. The source runs them as the Google service account google_service_account.server; a pod on STACKIT has no Google identity, and there is no default model.
Then: No other job on the board waits for it.
— review/inputs.yaml
Answer target.egress INP-TSE-eac97a7eefd2
State: not answered
Customer ArchitectLater — This build records an answer to this request and does not change the draft; configure it in the target environment: set egress.mode (ROUTED_DEFAULT, VIA_AREA_NEXT_HOP or NONE) in the target environment file given with --target-environment; the networks, route tables and security groups the draft writes follow it (AWS sources, the target environment description in the product documentation, Network policy). Not target.network.egress, which is a separate request that this build applies.
Needs: How outbound traffic leaves the migrated networks: the routed default, an address in a Network Area, or not at all.
Then: No other job on the board waits for it.
— —
Answer target.ingress.public INP-TSE-d73c02f8659b
State: not answered
Customer ArchitectLater — This build records an answer to this request and does not change the draft; configure it in the target environment: set ingress.public (ALLOW_PUBLIC_IP, LB_ONLY or NONE) in the target environment file given with --target-environment; the public addresses and load balancers the draft writes follow it (AWS sources, the target environment description in the product documentation, Network policy).
Needs: Whether a server may have a public address, only a load balancer may be public, or nothing is public.
Then: No other job on the board waits for it.
— —
Answer target.observability INP-TSE-d16ba37f3e2f
State: not answered
Customer ArchitectLater — This build records an answer to this request and does not change the draft; configure it in the target environment: keep or create the STACKIT Observability and Logs instances in the project yourself; this build applies no statement of it, and the observability section of the target environment file is read and bound only. Where the source has alarms, logs or metrics the draft creates its own instances, and reusing an existing one is an edit of the draft by hand.
Needs: Whether metrics and logs go to instances the draft creates, to existing instances, or nowhere.
Then: No other job on the board waits for it.
— —
Answer target.project INP-TSE-3f99c0e1bfaf
State: not answered
Customer ArchitectLater — This build records an answer to this request and does not change the draft; configure it in the target environment: set the variable project_id of the draft (terraform.tfvars, or TF_VAR_project_id for the scripts); a project.id in a target environment file is read and bound and is not written into the draft.
Needs: The STACKIT project the migrated estate is built in.
Then: No other job on the board waits for it.
— —
Review the critical settings of a Cloud Run service (Identity Architect) DEC-IAM-GOOGLE-CLOUD-RUN-V2-JOB-MIGRATE
State: open input
Step: The setting service-identity of google_cloud_run_v2_job.migrate MAN/semantic/google_cloud_run_v2_job.migrate/service-identity
Identity ArchitectLater — Review the service identity setting: The ledger entry reads preserved or transformed with a value that is a fact of the source, or a person accepts the difference.
Then: No other job on the board waits for it.
— —
Review the critical settings of a Cloud Run service (Network Architect) DEC-NET-GOOGLE-CLOUD-RUN-V2-JOB-MIGRATE
State: open input
Step: The setting cloud-run-v2-job-network-exposure of google_cloud_run_v2_job.migrate MAN/semantic/google_cloud_run_v2_job.migrate/cloud-run-v2-job-network-exposure
Network ArchitectLater — Review the cloud run v2 job network exposure setting: A person confirms the value against the target, or the knowledge base gains a rule that decides this setting.
Then: No other job on the board waits for it.
— —
Review the critical settings of a Cloud Run service (Security Architect) DEC-SEC-GOOGLE-CLOUD-RUN-V2-JOB-MIGRATE
State: open input
Step: The setting secrets of google_cloud_run_v2_job.migrate MAN/semantic/google_cloud_run_v2_job.migrate/secrets
Security ArchitectLater — Create the Kubernetes Secrets for the Secret Manager references: A person creates the Kubernetes Secrets the manifest lists, filled from STACKIT Secrets Manager (for example with an External Secrets Operator).
Then: No other job on the board waits for it.
— —
Review the critical settings of a Cloud Run service DEC-GEN-GOOGLE-CLOUD-RUN-V2-SERVICE-SERVER
State: open input
Step: The review of the open settings of google_cloud_run_v2_service.server by the Platform Architect MAN/semantic/google_cloud_run_v2_service.server/open-settings-platform-architect
Platform ArchitectLater — Review the IAM policy grant setting: A person decides what this finding asks, and records the evidence or the decision. The finding says: A full IAM policy (member/role bindings) is set directly on the service via policy_data; STACKIT has no per-service IAM policy resource, so who may invoke the migrated SKE workload is decided by a person — the draft carries no invocation check.
Then: No other job on the board waits for it.
— —
Review the critical settings of a Cloud Run service (Identity Architect) DEC-IAM-GOOGLE-CLOUD-RUN-V2-SERVICE-SERVER
State: open input
Step: The review of the open settings of google_cloud_run_v2_service.server by the Identity Architect MAN/semantic/google_cloud_run_v2_service.server/open-settings-identity-architect
Identity ArchitectLater — Decide who may invoke the service: A person decides how callers of the workload are authenticated (in the application, behind an authenticating proxy, or by no exposure at all) and how the SKE exposure is set, since the draft carries no invocation check. Review the service identity setting: The ledger entry reads preserved or transformed with a value that is a fact of the source, or a person accepts the difference.
Then: No other job on the board waits for it.
— —
Review the critical settings of a Cloud Run service (Network Architect) DEC-NET-GOOGLE-CLOUD-RUN-V2-SERVICE-SERVER
State: open input
Step: The setting cloud-sql-connection of google_cloud_run_v2_service.server MAN/semantic/google_cloud_run_v2_service.server/cloud-sql-connection
Network ArchitectLater — Decide how the service connects to the database: A person points the workload at the endpoint of the migrated database instance (a Flex or MariaDB instance) over TLS, because the Cloud SQL connector socket has no counterpart.
Then: No other job on the board waits for it.
— —
Review the critical settings of a Cloud Run service (Security Architect) DEC-SEC-GOOGLE-CLOUD-RUN-V2-SERVICE-SERVER
State: open input
Step: The review of the open settings of google_cloud_run_v2_service.server by the Security Architect MAN/semantic/google_cloud_run_v2_service.server/open-settings-security-architect
Security ArchitectLater — Confirm the environment settings: A person fills in the values the manifest lists as not copied, in the ConfigMap on the cluster. Create the Kubernetes Secrets for the Secret Manager references: A person creates the Kubernetes Secrets the manifest lists, filled from STACKIT Secrets Manager (for example with an External Secrets Operator).
Then: No other job on the board waits for it.
— —
Review the critical settings of a Cloud Build (Identity Architect)
State: open input
3 jobs of alike steps: google_cloudbuild_trigger.activategcb, google_cloudbuild_trigger.init, google_cloudbuild_trigger.placeholder

Then, for each job: No other job on the board waits for it.

Identity ArchitectLater — Review the build identity setting: A person decides the setting with what replaces the unit once the architect has chosen it, or the knowledge base gains a rule that decides this setting. — One file for each job, listed under it.
Review the critical settings of a Cloud Build (Platform Architect) DEC-OPS-GOOGLE-CLOUDBUILD-TRIGGER-ACTIVATEGCB
State: open input
Platform ArchitectLater — Confirm its dependency on the references: A person confirms how the replacement carries the relation, or accepts the difference. Choose the container image or artifact: A person decides the setting with what replaces the unit once the architect has chosen it, or the knowledge base gains a rule that decides this setting. Confirm the entry point of the function: A person decides the setting with what replaces the unit once the architect has chosen it, or the knowledge base gains a rule that decides this setting. Review the log destination setting: A person decides the setting with what replaces the unit once the architect has chosen it, or the knowledge base gains a rule that decides this setting.
Then: No other job on the board waits for it.
— —
Review the critical settings of a Cloud Build (Platform Architect) DEC-OPS-GOOGLE-CLOUDBUILD-TRIGGER-INIT
State: open input
Platform ArchitectLater — Confirm its dependency on the references: A person confirms how the replacement carries the relation, or accepts the difference. Choose the container image or artifact: A person decides the setting with what replaces the unit once the architect has chosen it, or the knowledge base gains a rule that decides this setting. Confirm the entry point of the function: A person decides the setting with what replaces the unit once the architect has chosen it, or the knowledge base gains a rule that decides this setting. Review the log destination setting: A person decides the setting with what replaces the unit once the architect has chosen it, or the knowledge base gains a rule that decides this setting.
Then: No other job on the board waits for it.
— —
Review the critical settings of a Cloud Build DEC-GEN-GOOGLE-CLOUDBUILD-TRIGGER-PLACEHOLDER
State: open input
Owner assignment requiredLater — Decide which firebase hosting site this resource depends on: The contract of this unit gains a semantic that reads google_firebase_hosting_site (and lists it as carried), or a person decides what the reference to the resource becomes.
Then: No other job on the board waits for it.
— —
Review the critical settings of a Cloud Build (Platform Architect) DEC-OPS-GOOGLE-CLOUDBUILD-TRIGGER-PLACEHOLDER
State: open input
Platform ArchitectLater — Confirm its dependency on the references: A person confirms how the replacement carries the relation, or accepts the difference. Choose the container image or artifact: A person decides the setting with what replaces the unit once the architect has chosen it, or the knowledge base gains a rule that decides this setting. Review the log destination setting: A person decides the setting with what replaces the unit once the architect has chosen it, or the knowledge base gains a rule that decides this setting.
Then: No other job on the board waits for it.
— —
Review the critical settings of a firebase hosting site (Identity Architect) DEC-IAM-GOOGLE-FIREBASE-HOSTING-SITE-CLIENT
State: open input
Identity ArchitectLater — Confirm the project of the firebase hosting site: A person decides which STACKIT project, and with it which access rules, holds the replacement.
Then: No other job on the board waits for it.
— —
Review the critical settings of a firebase hosting site (Platform Architect) DEC-OPS-GOOGLE-FIREBASE-HOSTING-SITE-CLIENT
State: open input
Platform ArchitectLater — Confirm the site ID of the firebase hosting site: A person sets this up on the bucket, the CDN distribution and the domain that replace Firebase Hosting, or decides to drop it, and records the decision.
Then: No other job on the board waits for it.
— —
Review the critical settings of a Pub/Sub topic (Platform Architect) DEC-OPS-GOOGLE-PUBSUB-TOPIC-FAUX
State: open input
Step: The setting "name" of google_pubsub_topic.faux MAN/semantic/google_pubsub_topic.faux/tc-name
Platform ArchitectLater — Confirm the name of the resource on the target: A person confirms the topic name the replacement messaging service carries against the publishers and subscribers that use it, or accepts the new name.
Then: No other job on the board waits for it.
— —
Review the critical settings of a Secret Manager secret (Identity Architect) DEC-IAM-GOOGLE-SECRET-MANAGER-SECRET-DJANGO-ADMIN-PASSWORD
State: open input
Step: The setting secret-settings of google_secret_manager_secret.django_admin_password MAN/semantic/google_secret_manager_secret.django_admin_password/secret-settings
Identity ArchitectLater — Decide how the secrets are carried: A person recreates the secret in the Secrets Manager instance, since its data is not written into the draft, and decides for each IAM member whether it gets a user of the whole instance, a role binding on a secret group, or a separate instance.
Then: No other job on the board waits for it.
— —
Review the critical settings of a Secret Manager secret (Security Architect) DEC-SEC-GOOGLE-SECRET-MANAGER-SECRET-DJANGO-ADMIN-PASSWORD
State: open input
Step: The review of the open settings of google_secret_manager_secret.django_admin_password MAN/semantic/google_secret_manager_secret.django_admin_password/open-settings-security-architect
Security ArchitectLater — Provide the values of the secrets: A person decides where the value comes from, supplies the document and the step has run. Confirm the name of the secret: A person confirms the secret name in STACKIT Secrets Manager against what refers to the source secret ID, or accepts the new name.
Then: No other job on the board waits for it.
— —
Review the critical settings of a Secret Manager secret (Identity Architect) DEC-IAM-GOOGLE-SECRET-MANAGER-SECRET-DJANGO-SETTINGS
State: open input
Step: The setting secret-settings of google_secret_manager_secret.django_settings MAN/semantic/google_secret_manager_secret.django_settings/secret-settings
Identity ArchitectLater — Decide how the secrets are carried: A person recreates the secret in the Secrets Manager instance, since its data is not written into the draft, and decides for each IAM member whether it gets a user of the whole instance, a role binding on a secret group, or a separate instance.
Then: No other job on the board waits for it.
— —
Review the critical settings of a Secret Manager secret (Security Architect) DEC-SEC-GOOGLE-SECRET-MANAGER-SECRET-DJANGO-SETTINGS
State: open input
Step: The review of the open settings of google_secret_manager_secret.django_settings MAN/semantic/google_secret_manager_secret.django_settings/open-settings-security-architect
Security ArchitectLater — Provide the values of the secrets: A person decides where the value comes from, supplies the document and the step has run. Confirm the name of the secret: A person confirms the secret name in STACKIT Secrets Manager against what refers to the source secret ID, or accepts the new name.
Then: No other job on the board waits for it.
— —
Review the critical settings of a service account (Identity Architect)
State: open input
4 jobs of alike steps: google_service_account.automation, google_service_account.client, google_service_account.init and 1 more

Needs, for each job: the members that act as or manage the service account
Then, for each job: No other job on the board waits for it.

Identity ArchitectLater — Review the account name setting: A person decides what this finding asks, and records the evidence or the decision. The finding says: The account ID is not visible statically; the STACKIT account is named after the source address. — a variable's default, not a fact. Map the IAM roles of the service account to STACKIT roles: The knowledge base's note on this setting states no closing condition; it is done when a person has chosen a way out above, recorded the choice, and the target is checked as the verification says. Map the IAM roles of the service account to STACKIT roles: A person confirms the value against the target, or the knowledge base gains a rule that decides this setting. — One file for each job, listed under it.
Review the critical settings of a Cloud SQL instance (Identity Architect) DEC-IAM-GOOGLE-SQL-DATABASE-INSTANCE-POSTGRES
State: open input
Step: The setting database-users of google_sql_database_instance.postgres MAN/semantic/google_sql_database_instance.postgres/database-users
Identity ArchitectLater — Review the database users setting: A literal value or a resolved reference in the source lets the check decide, or a person verifies the value.
Then: No other job on the board waits for it.
— —
Review the critical settings of a Cloud SQL instance (Network Architect) DEC-NET-GOOGLE-SQL-DATABASE-INSTANCE-POSTGRES
State: open input
Step: The setting user-and-database-settings of google_sql_database_instance.postgres MAN/semantic/google_sql_database_instance.postgres/user-and-database-settings
Network ArchitectLater — Review the user and database settings setting: A person confirms the value against the target, or the knowledge base gains a rule that decides this setting.
Then: No other job on the board waits for it.
— —
Review the critical settings of a Cloud SQL instance (Platform Architect) DEC-OPS-GOOGLE-SQL-DATABASE-INSTANCE-POSTGRES
State: open input
Step: The review of the open settings of google_sql_database_instance.postgres "open-settings-platform-architect" MAN/semantic/google_sql_database_instance.postgres/open-settings-platform-architect
Platform ArchitectLater — Confirm the name of the resource on the target: A person confirms the instance name the STACKIT database carries against what refers to the source instance name, or accepts the new name. Confirm the name of the SQL database: A person confirms the value against the target, or the knowledge base gains a rule that decides this setting.
Then: No other job on the board waits for it.
— —
Review the critical settings of a Cloud Storage bucket (Storage Architect) DEC-DATA-GOOGLE-STORAGE-BUCKET-MEDIA
State: open input
Storage ArchitectLater — Confirm whether the bucket may be deleted with its contents: A person accepts the difference or the design changes: nothing in the source can make the target carry it.
Then: No other job on the board waits for it.
— —
Review the critical settings of a Cloud Storage bucket DEC-GEN-GOOGLE-STORAGE-BUCKET-MEDIA
State: open input
Step: The setting iam-access of google_storage_bucket.media MAN/semantic/google_storage_bucket.media/iam-access
Storage ArchitectLater — Review the IAM access setting: A person decides it as that finding asks, and the finding's closing evidence or decision is recorded. A person creates the bucket policies and Object Storage credentials that give the same access on STACKIT.
Then: No other job on the board waits for it.
— —
Review the critical settings of a Cloud Storage bucket (Identity Architect) DEC-IAM-GOOGLE-STORAGE-BUCKET-MEDIA
State: open input
Step: The review of the open settings of google_storage_bucket.media MAN/semantic/google_storage_bucket.media/open-settings-identity-architect
Identity ArchitectLater — Review the IAM grant setting: A person decides what this finding asks, and records the evidence or the decision. The finding says: Bucket access is granted with IAM bindings or ACL entries; on STACKIT it becomes bucket policies and Object Storage credentials. Review the public access setting: A literal value or a resolved reference in the source lets the check decide, or a person verifies the value.
Then: No other job on the board waits for it.
— —
Review the critical settings of a Cloud Storage bucket (Platform Architect) DEC-OPS-GOOGLE-STORAGE-BUCKET-MEDIA
State: open input
Step: The setting "name" of google_storage_bucket.media MAN/semantic/google_storage_bucket.media/tc-storage-bucket-name
Platform ArchitectLater — Confirm the name of the Cloud Storage bucket: A person confirms the Object Storage bucket name against the applications and tools that use the source bucket name, or accepts the new name.
Then: No other job on the board waits for it.
— —
Review the critical settings of a Cloud Storage bucket (Security Architect) DEC-SEC-GOOGLE-STORAGE-BUCKET-MEDIA
State: open input
Step: The setting geo-replication of google_storage_bucket.media MAN/semantic/google_storage_bucket.media/geo-replication
Security ArchitectLater — Decide the geo-replication: The value is set where the module is called (a literal), the variable is given its value in a variable file of the scan (--var-file), or a person confirms the value production uses.
Then: No other job on the board waits for it.
— —

Approve a design (10 jobs)

JobOwnerPriorityBlocked byCloses whenEvidenceGenerated file
Allow the calls of STACKIT APIs that are not generally available DEC-GEN-CONVERT-API-OPT-IN
State: open input
Step: The step "Create the topic under a displayName of 1 to 36 letters, digits, spaces and…" MAN/pubsub.topic/name/google_pubsub_topic.faux
Platform ArchitectFirst — Every API the record lists is answered in the decisions file: allowed, or refused.
Needs: the Secrets Manager Vault-compatible API is of a maturity that is not established (its documentation states no release status and its product documentation does not establish it as generally available): the execution plan executes no call of an API that is not generally available without an explicit opt-in, so the calls of it and the steps of its path for google_secret_manager_secret.django_admin_password, google_secret_manager_secret.django_settings wait for this decision; the draft's own blocks do not | the pubsub API v1beta is beta: the execution plan executes no call of an API that is not generally available without an explicit opt-in, so the calls of it and the steps of its path for google_pubsub_topic.faux wait for this decision; the draft's own blocks do not | the platform's consent to depend on an API that may change or vanish (alpha, beta, or a maturity the documentation does not establish)
Then: Brings closer once it is done (each waits for more): Run the STACKIT API step WriteSecret of… and 2 more.
  • https://github.com/stackitcloud/stackit-api-specifications/blob/main/services/functions/v1alpha/functions.json#L767-L771
—
Choose how the data is moved DEC-GEN-CONVERT-DATA-MOVEMENT
State: open input
Data ArchitectHolds steps — An answer whose effect frees the steps that wait for it: an acknowledgement of the current draft in the decisions file given with --decisions (decisions-template.yaml), or the inputs answer (or the change of the source) that makes the draft carry another option.
Needs: the plan defines both methods of the engine (a dump restored inside the write freeze, and a logical replication that follows the changes until the freeze) and keeps them open: which one applies depends on the size of the data, the write rate and the downtime the business accepts, and the source states none of them; the steps of the methods wait for the answer | the size of the data, the downtime the business tolerates and the consistency the application needs, to choose the method and the cutover window
Then: Brings closer once it is done (each waits for more): Source: turn logical decoding on: set the flag… and 7 more.
  • https://github.com/stackitcloud/terraform-provider-stackit/blob/v0.119.0/docs/resources/mariadb_credential.md#L51-L57
  • https://github.com/stackitcloud/terraform-provider-stackit/blob/v0.119.0/docs/resources/mongodbflex_user.md#L59-L63
  • https://github.com/stackitcloud/terraform-provider-stackit/blob/v0.119.0/docs/resources/opensearch_credential.md#L51-L57
  • https://github.com/stackitcloud/terraform-provider-stackit/blob/v0.119.0/docs/resources/valkey_credential.md#L51-L57
  • https://docs.stackit.cloud/products/databases/mariadb/how-tos/backup-and-restore/
  • https://docs.stackit.cloud/products/databases/sqlserver-flex/how-tos/import-database-backup-from-stackit-s3-into-sqlserver-flex/
  • https://docs.stackit.cloud/products/databases/key-value-store/tutorials/migrate-data-to-a-new-instance/
  • https://docs.aws.amazon.com/AmazonElastiCache/latest/dg/SupportedCommands.html
  • https://docs.aws.amazon.com/memorydb/latest/devguide/restrictedcommands.html
  • https://docs.stackit.cloud/products/databases/opensearch/how-tos/migrate-elasticsearch-data-to-an-opensearch2-service-instance/
  • https://docs.aws.amazon.com/AmazonS3/latest/userguide/replication.html
  • https://www.postgresql.org/docs/current/logical-replication-restrictions.html
  • https://www.postgresql.org/docs/current/sql-createsubscription.html
  • https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/PostgreSQL.Concepts.General.FeatureSupport.LogicalReplication.html
  • https://docs.stackit.cloud/products/storage/object-storage/tutorials/migrate-data-using-rclone/
  • https://rclone.org/commands/rclone_copy/
  • https://rclone.org/commands/rclone_check/
  • https://docs.stackit.cloud/products/storage/object-storage/reference/supported-operations-on-buckets-and-objects/
  • https://docs.aws.amazon.com/cli/latest/reference/s3/sync.html
  • https://docs.aws.amazon.com/cli/v1/userguide/cli-configure-options.html
  • https://docs.stackit.cloud/products/storage/object-storage/how-tos/manage-encryption/
—
Decide whether a proposed STACKIT alternative replaces a source capability DEC-GEN-CONVERT-PROPOSED-ALTERNATIVE
State: open input
4 steps of the plan
  • The proposed alternative of google_firebase_hosting_site.client MAN/unit/google_firebase_hosting_site.client
  • The proposed alternative of google_cloudbuild_trigger.activategcb MAN/unit/google_cloudbuild_trigger.activategcb
  • The proposed alternative of google_cloudbuild_trigger.init MAN/unit/google_cloudbuild_trigger.init
  • The proposed alternative of google_cloudbuild_trigger.placeholder MAN/unit/google_cloudbuild_trigger.placeholder
Platform ArchitectHolds steps — An answer whose effect frees the steps that wait for it: an acknowledgement of the current draft in the decisions file given with --decisions (decisions-template.yaml), or the inputs answer (or the change of the source) that makes the draft carry another option.
Needs: the target has no equal of this Cloud Build trigger: starts a build on a source event, a Pub/Sub message, a webhook or by hand, with its steps, substitutions, artifacts, secrets and optional approval: Nothing is converted. The same delivery is a workflow of STACKIT Git Pipelines (written for GitHub Actions; STACKIT-managed or custom runners; secrets from Secrets Manager or the repository; a manual-approval action) or the customer's own CI/CD. Trigger conditions, steps, secrets (created again, never copied), the service account (replaced by the credentials the workflow uses against STACKIT), the log destination and the approval are written again by a person. To decide: Which pipelines are still needed, where they run (STACKIT Git Pipelines or the customer's own CI/CD), how each trigger, step, secret and approval is written again, and who owns the workflow files. | the target has no equal of this one member's role on the Cloud Storage bucket: A STACKIT credentials group is not a grant on the Cloud Storage bucket. It is the principal that a bucket policy names, a set of S3 keys with no Google identity behind it, and by itself it gives no access to the bucket and takes none away. The statement that grants it something is a statement of the bucket policy, in the policy language of STACKIT (a credentials group or * as the principal, S3 actions, five condition keys), which no Terraform resource sets. The Google role is not mapped to S3 actions by any table, the condition of the grant has no counterpart unless it can be written with those five condition keys, and a Google group, a domain, a federated identity and allUsers or allAuthenticatedUsers are named again as credentials groups or as *. To decide: Which credentials group stands for each member of the grant, which S3 actions of the bucket policy give the same people the access they need and no more than the Google role gave, what becomes of the condition, of public members (allUsers, allAuthenticatedUsers), of Google groups, domains and federated identities, and whether the grant ends with the Cloud Storage bucket when it has no replacement. Which bucket the grant is on, because the scan does not hold it. The draft of google_storage_bucket.media stands as it is: this answer decides the module and nothing of that draft. | the target has no equal of this static web hosting site: Static files are published into an Object Storage bucket by a pipeline, and a CDN distribution (a beta resource) with the bucket as origin serves them on a custom domain; the redirects of the site become redirect rules of the distribution. Custom response headers, rewrites to Cloud Run services or Cloud Functions, preview channels and the release history have no counterpart and are restated in the pipeline or in the application. To decide: Which bucket is the origin, which domain the distribution serves, and how rewrites and previews are replaced. The CDN resources are beta. | the target has no equal of this the members of one role on the Secret Manager secret: A STACKIT role assignment is not a grant on the Secret Manager secret. It gives one user, group or service account one STACKIT role on a whole project, folder or organisation. The role is a set of STACKIT permissions, not the Google role, and no table maps one to the other. It has no condition and no public member, so what the grant gave to a Google group, a domain, a federated identity or everyone is named again, and the access reaches more than the Secret Manager secret. A binding on a secret group applies to every secret in the group, so it is wider than a grant on one secret unless the secret has a group of its own, and its roles are Secrets Manager roles. The binding was authoritative for its role: STACKIT role assignments are additive, so a person who holds the role through another assignment keeps it, and removing such people is a step of a person. To decide: Which STACKIT role, on which project, folder or organisation, gives the same people the access they need on the Secret Manager secret, knowing it covers everything in that scope; which STACKIT users, groups or service accounts take the place of Google groups, domains, federated identities and a public member; and whether the grant ends with the Secret Manager secret when it has no replacement. For secrets: which secret group holds the secret, who else shares that group, and which Secrets Manager role and subject take the grant. Whether people who hold the role through another assignment keep it. The draft of google_secret_manager_secret.django_admin_password stands as it is: this answer decides the module and nothing of that draft. | the target has no equal of this the members of one role on the Secret Manager secret: A STACKIT role assignment is not a grant on the Secret Manager secret. It gives one user, group or service account one STACKIT role on a whole project, folder or organisation. The role is a set of STACKIT permissions, not the Google role, and no table maps one to the other. It has no condition and no public member, so what the grant gave to a Google group, a domain, a federated identity or everyone is named again, and the access reaches more than the Secret Manager secret. A binding on a secret group applies to every secret in the group, so it is wider than a grant on one secret unless the secret has a group of its own, and its roles are Secrets Manager roles. The binding was authoritative for its role: STACKIT role assignments are additive, so a person who holds the role through another assignment keeps it, and removing such people is a step of a person. To decide: Which STACKIT role, on which project, folder or organisation, gives the same people the access they need on the Secret Manager secret, knowing it covers everything in that scope; which STACKIT users, groups or service accounts take the place of Google groups, domains, federated identities and a public member; and whether the grant ends with the Secret Manager secret when it has no replacement. For secrets: which secret group holds the secret, who else shares that group, and which Secrets Manager role and subject take the grant. Whether people who hold the role through another assignment keep it. The draft of google_secret_manager_secret.django_settings stands as it is: this answer decides the module and nothing of that draft. | that the stated difference from the source is acceptable for what depends on it | the values the module asks for, which the draft does not invent
Then: No other job on the board waits for it.
  • https://opentofu.org/docs/language/meta-arguments/count/
—
State where the units of each source project of the estate go DEC-GEN-CONVERT-SOURCE-PROJECT-MAPPING
State: open input
Step: The review of the open settings of google_sql_database_instance.postgres "SOURCE_PROJECT_MAPPING" MAN/estate/SOURCE_PROJECT_MAPPING
Platform ArchitectHolds steps — A person decides the setting with what replaces the unit once the architect has chosen it, or the knowledge base gains a rule that decides this setting. A person confirms the value against the target, or the knowledge base gains a rule that decides this setting. The module terraform/proposals/proposal_activategcb is switched on with its values and checked, or the design that replaces it is set up and checked; the decision records which. The module terraform/proposals/proposal_init is switched on with its values and checked, or the design that replaces it is set up and checked; the decision records which. The module terraform/proposals/proposal_placeholder is switched on with its values and checked, or the design that replaces it is set up and checked; the decision records which.
Needs: The source places its units in the project example-project, and in a project the scan cannot read for some units, and the source project is carried nowhere. A person maps the source projects by answering target.project.source_project for each: var.project_id, or the project of the unit's network (network-project). The answer records that mapping and changes nothing in the draft, which keeps its own project resolver. | which source projects stay one STACKIT project and which do not, and who owns each | what the customer decides: Which pipelines are still needed, where they run (STACKIT Git Pipelines or the customer's own CI/CD), how each trigger, step, secret and approval is written again, and who owns the workflow files. the review the assessment asks for: Write the workflow in the repository: one job (or step) per build step, with the same container images or their STACKIT equivalents; Recreate every secret the build reads in STACKIT Secrets Manager (read with the vault action) or as a repository secret; the values of the source are never copied; Write the trigger conditions again as the on: section of the workflow and verify each event kind against the Forgejo Actions reference; Decide where images and artifacts go: the package registry of STACKIT Git takes container images from any OCI client, or keep your own registry, and change the image names in the deploy steps.; whether google_cloudbuild_trigger.activategcb exists in production, and with how many instances: the value production gives var.init | what the customer decides: Which pipelines are still needed, where they run (STACKIT Git Pipelines or the customer's own CI/CD), how each trigger, step, secret and approval is written again, and who owns the workflow files. the review the assessment asks for: Write the workflow in the repository: one job (or step) per build step, with the same container images or their STACKIT equivalents; Recreate every secret the build reads in STACKIT Secrets Manager (read with the vault action) or as a repository secret; the values of the source are never copied; Write the trigger conditions again as the on: section of the workflow and verify each event kind against the Forgejo Actions reference; Decide where images and artifacts go: the package registry of STACKIT Git takes container images from any OCI client, or keep your own registry, and change the image names in the deploy steps.; whether google_cloudbuild_trigger.init exists in production, and with how many instances: the value production gives var.init | what the customer decides: Which pipelines are still needed, where they run (STACKIT Git Pipelines or the customer's own CI/CD), how each trigger, step, secret and approval is written again, and who owns the workflow files. the review the assessment asks for: Write the workflow in the repository: one job (or step) per build step, with the same container images or their STACKIT equivalents; Recreate every secret the build reads in STACKIT Secrets Manager (read with the vault action) or as a repository secret; the values of the source are never copied; Write the trigger conditions again as the on: section of the workflow and verify each event kind against the Forgejo Actions reference; Decide where images and artifacts go: the package registry of STACKIT Git takes container images from any OCI client, or keep your own registry, and change the image names in the deploy steps.; whether google_cloudbuild_trigger.placeholder exists in production, and with how many instances: the value production gives var.init
Then: No other job on the board waits for it.
  • https://github.com/stackitcloud/terraform-provider-stackit/blob/v0.119.0/docs/resources/network.md
—
Map each source location of the estate to a STACKIT region DEC-GEN-CONVERT-SOURCE-REGION-MAPPING
State: open input
Step: The review of the open settings of google_cloud_run_v2_job.migrate, google_cloud_run_v2_service.server, google_sql_database_instance.postgres and 1 more MAN/estate/SOURCE_REGION_MAPPING
Platform ArchitectHolds steps — A person confirms the STACKIT region of the SKE cluster the workload runs on holds the residency the source region gave, since no mapping between Google and STACKIT regions is evidenced. A person confirms the STACKIT region of the instance (and of a read replica, decided with its primary) holds the residency the source region gave. A person confirms the value against the target, or the knowledge base gains a rule that decides this setting.
Needs: The source places its units in a location the scan cannot read (the value comes from an input a plan can change, or the source does not state it). No mapping between Google and STACKIT regions is evidenced, so the region the draft builds in is not shown to hold the residency of a source location: a person states it once for the estate, by answering target.region.source_location for each location. | the residency requirement behind each source location (a law, a contract, a policy) and the STACKIT region that meets it
Then: No other job on the board waits for it.
  • https://docs.stackit.cloud/platform/regions/
—
Review the critical settings of a Cloud Run service (Platform Architect) DEC-OPS-GOOGLE-CLOUD-RUN-V2-JOB-MIGRATE
State: open input
2 steps of the plan
  • The review of the open settings of google_cloud_run_v2_job.migrate MAN/semantic/google_cloud_run_v2_job.migrate/open-settings-platform-architect
  • The step "Fill in the required inputs of kubernetes/migrate/manifests.yaml and apply it…" MAN/draft/kubernetes/migrate/manifests-yaml
Platform ArchitectLater — Choose the container image or artifact: A person confirms the executable artifact or image for the STACKIT target: where it is built or pulled from and that the same build runs there. For each of 4 settings (Confirm the entry point of the function; Confirm the name of the cloud run v2 job; Confirm the name of the env entry of the containers of the template of the template of the cloud run v2 job; Confirm the name of the volumes entry of the template of the template of the cloud run v2 job): A person confirms the value against the target, or the knowledge base gains a rule that decides this setting. Review the k4 cloud run volume mount cloud run v2 job setting: A person provides the data in the target workload at the path the application expects, with an owner and mode it can use, and checks that it finds its files. Review the terraform destroy guard setting: A person decides whether the replacement keeps the guard with lifecycle { prevent_destroy = true } in the Terraform code.
Needs: where the image is built or pulled from
Then: No other job on the board waits for it.
— terraform/kubernetes/migrate/manifests.yaml
Review the critical settings of a Cloud Run service (Platform Architect) DEC-OPS-GOOGLE-CLOUD-RUN-V2-SERVICE-SERVER
State: open input
Platform ArchitectLater — Choose the container image or artifact: A person confirms the executable artifact or image for the STACKIT target: where it is built or pulled from and that the same build runs there. Decide how the volume mounts are carried: A person provides the data in the target workload at the path the application expects, with an owner and mode it can use, and checks that it finds its files. Confirm the name of the Cloud Run service: A person confirms the workload name on the cluster against what addresses or refers to the Cloud Run service name, or accepts the new name. Confirm the name of the volumes entry of the template of the Cloud Run service: A person keeps each volume name matched with the volume mount that refers to it when the volumes are rebuilt as workload volumes on the cluster. Review the terraform destroy guard setting: A person decides whether the replacement keeps the guard with lifecycle { prevent_destroy = true } in the Terraform code.
Needs: where the image is built or pulled from
Then: No other job on the board waits for it.
— —
Review the critical settings of a firebase project (Identity Architect) DEC-IAM-GOOGLE-FIREBASE-PROJECT-DEFAULT
State: blocked
Identity ArchitectLater — Confirm the project of the firebase project: A person decides which STACKIT project, and with it which access rules, holds the replacement.
Then: No other job on the board waits for it.
— —
Approve a redesign: the target cannot carry the critical setting force-destroy of google_storage_bucket.media safely (the target has no counterpart that carries this setting of the source)
State: refused
The refusal of the setting force-destroy of google_storage_bucket.media REF/semantic/google_storage_bucket.media/force-destroy
Storage ArchitectHolds steps — Not stated: the plan names no redesign.
Then: No other job on the board waits for it.
— —
Approve a redesign: the target cannot carry google_firebase_project.default (google_firebase_project) safely (no STACKIT service or resource carries this source resource)
State: refused
The refusal of google_firebase_project.default REF/unit/google_firebase_project.default
Owner assignment requiredHolds steps — A redesign is approved (the plan suggests: List the Firebase services each app uses (authentication, database, storage, messaging, remote config); each needs its own replacement; The signing keys and store listings stay with Google Play and the Apple App Store; only the backend the app talks to moves.).
Then: No other job on the board waits for it.
— —

Perform migration work (38 jobs)

JobOwnerPriorityBlocked byCloses whenEvidenceGenerated file
Service account: manual review DEC-IAM-STACKITSA-STATEMENT-MANUAL-REVIEW
State: manual work
2 steps of the plan
  • The step "Decide how google_cloud_run_v2_job.migrate gets its application identity on…" MAN/identity/facts:google_cloud_run_v2_job.migrate:google_cloud_run_v2_job.migrate.template.0.template.0.service_account-8dc3e1
  • The step "Decide how google_cloud_run_v2_service.server gets its application identity on…" MAN/identity/facts:google_cloud_run_v2_service.server:google_cloud_run_v2_service.server.template.0.service_account-5ccce9
Identity ArchitectLater — The identity fact of google_cloud_run_v2_job.migrate (template[0].template[0].service_account of google_cloud_run_v2_job.migrate names google_service_account.automation) is decided on STACKIT and recorded, or recorded as not needed. The identity fact of google_cloud_run_v2_service.server (template[0].service_account of google_cloud_run_v2_service.server names google_service_account.server) is decided on STACKIT and recorded, or recorded as not needed.
Then: No other job on the board waits for it.
— —
Service account: not drafted DEC-IAM-STACKITSA-STATEMENT-NOT-DRAFTED
State: manual work
2 steps of the plan
  • The step "Decide who may use the STACKIT service account written for…" for google_service_account.automation MAN/identity/held:principal:google_service_account.automation
  • The step "Decide who may use the STACKIT service account written for…" for google_service_account.server MAN/identity/held:principal:google_service_account.server
Identity ArchitectLater — The people and the workloads that may use the service account written for google_service_account.automation are named, and the roles it holds are stated. The people and the workloads that may use the service account written for google_service_account.server are named, and the roles it holds are stated.
Then: No other job on the board waits for it.
— —
Apply the blocks of terraform/security.tf with OpenTofu
State: open input
2 steps of the plan
  • The OpenTofu step for stackit_secretsmanager_instance.migrated_secrets TF/stackit_secretsmanager_instance.migrated_secrets
  • The OpenTofu step for stackit_secretsmanager_user.migration TF/stackit_secretsmanager_user.migration
Identity ArchitectHolds steps — OpenTofu applies the blocks of terraform/security.tf and the checks of their steps in execution/verify/checks.md hold.
Needs: the variables the blocks read (terraform/variables.tf says which have no default): project_id
Then: Brings closer once it is done (each waits for more): Run the STACKIT API step WriteSecret of…
terraform/security.tf
Run the STACKIT API step WriteSecret of google_secret_manager_secret.django_admin_password
State: waits for decisions
The STACKIT API step WriteSecret of google_secret_manager_secret.django_admin_password API/secrets-manager-vault/WriteSecret/google_secret_manager_secret.django_admin_password
STACKIT API step, generated, tested offline
Identity ArchitectHolds steps DEC-GEN-CONVERT-API-OPT-IN The call answers as the plan expects and the checks of the step in execution/verify/checks.md hold.
Then: Brings closer once it is done (each waits for more): Read each migrated secret (google_secret_manager_secret.django_admin_p…
—
Run the STACKIT API step WriteSecret of google_secret_manager_secret.django_settings
State: waits for decisions
The STACKIT API step WriteSecret of google_secret_manager_secret.django_settings API/secrets-manager-vault/WriteSecret/google_secret_manager_secret.django_settings
STACKIT API step, generated, tested offline
Identity ArchitectHolds steps DEC-GEN-CONVERT-API-OPT-IN The call answers as the plan expects and the checks of the step in execution/verify/checks.md hold.
Then: Brings closer once it is done (each waits for more): Read each migrated secret (google_secret_manager_secret.django_admin_p…
—
Read each migrated secret (google_secret_manager_secret.django_admin_password and google_secret_manager_secret.django_settings) back from the Secrets Manager instance stackit_secretsmanager_instance.migrated_secrets before the migration user is removed: with its login, send the ReadSecret request of the write step (GET /v1/<instance id>/data/<path>, the path the write step names) and check that the secret has a current version, that its keys are the keys of the document you supplied, and that its values equal the document's (compare a hash of each value on your side; print none).
State: waits for decisions
The step "Read each migrated secret" MAN/path/secrets-migration/read-back
Security ArchitectHolds steps DEC-GEN-CONVERT-API-OPT-IN every migrated secret has a current version whose keys and values equal those of its document, or the difference is corrected with the write step and read back again
Needs: the documents named in the write steps' inputs (the STACKIT API step WriteSecret of google_secret_manager_secret.django_admin_password, the STACKIT API step WriteSecret of google_secret_manager_secret.django_settings) and the login of stackit_secretsmanager_user.migration (its outputs stackit_secretsmanager_user_migration_password and stackit_secretsmanager_user_migration_username)
Then: Brings closer once it is done (each waits for more): Remove the migration user stackit_secretsmanager_user.migration of…
— —
Remove the migration user stackit_secretsmanager_user.migration of the Secrets Manager instance stackit_secretsmanager_instance.migrated_secrets once the last secret is written and read back: delete its block and its two outputs (stackit_secretsmanager_user_migration_password and stackit_secretsmanager_user_migration_username) from the draft and run tofu apply, so the provider deletes the user. Afterwards the state must not list it (tofu state list shows no stackit_secretsmanager_user.migration) and the instance must list no user of that name; give a workload that reads a secret a user of its own with write_enabled = false, or the instance's role binding.
State: waits for decisions
The step "Remove the migration user stackit_secretsmanager_user.migration of the Secrets…" MAN/path/secrets-migration/retire-user
Security ArchitectLater DEC-GEN-CONVERT-API-OPT-IN the block and the two outputs of stackit_secretsmanager_user.migration are gone from the draft, the state lists no such user, and the instance lists no user created for the migration
Needs: the draft, the state of the draft and the Secrets Manager instance's list of users
Then: No other job on the board waits for it.
— —
Apply the blocks of terraform/identity.tf with OpenTofu
State: open input
4 steps of the plan
  • The OpenTofu step for stackit_service_account.automation TF/stackit_service_account.automation
  • The OpenTofu step for stackit_service_account.client TF/stackit_service_account.client
  • The OpenTofu step for stackit_service_account.init TF/stackit_service_account.init
  • The OpenTofu step for stackit_service_account.server TF/stackit_service_account.server
Identity ArchitectLater — OpenTofu applies the blocks of terraform/identity.tf and the checks of their steps in execution/verify/checks.md hold.
Needs: the variables the blocks read (terraform/variables.tf says which have no default): project_id
Then: No other job on the board waits for it.
terraform/identity.tf
Apply the block of terraform/storage.tf with OpenTofu
State: open input
The OpenTofu step for stackit_objectstorage_bucket.media TF/stackit_objectstorage_bucket.media
Storage ArchitectHolds steps — OpenTofu applies the blocks of terraform/storage.tf and the checks of their steps in execution/verify/checks.md hold.
Needs: the variables the blocks read (terraform/variables.tf says which have no default): media_bucket_name, project_id
Then: These can start once it is done: Close what the plan lists as UNKNOWN, from the move host, before any…
terraform/storage.tf
Close what the plan lists as UNKNOWN, from the move host, before any object moves. The credentials of the target are the environment names TARGET_ACCESS_KEY_ID and TARGET_SECRET_ACCESS_KEY, set in the shell of the move host at run time from the credential of a credentials group; the source uses the Google identity of that shell (the service account the host runs as, or a login you made for the move; rclone's env_auth takes it from the environment). No value is written into a file, a ticket or this plan. In the shell of the move host configure the two remotes from the environment: export RCLONE_CONFIG_SRC_TYPE="google cloud storage" RCLONE_CONFIG_SRC_ENV_AUTH=true RCLONE_CONFIG_DST_TYPE=s3 RCLONE_CONFIG_DST_PROVIDER=Other RCLONE_CONFIG_DST_ENDPOINT=https://object.storage.eu01.onstackit.cloud RCLONE_CONFIG_DST_ACCESS_KEY_ID="$TARGET_ACCESS_KEY_ID" RCLONE_CONFIG_DST_SECRET_ACCESS_KEY="$TARGET_SECRET_ACCESS_KEY" RCLONE_CONFIG_DST_ACL=private. Source: rclone lsd SRC:, rclone size SRC:<source-bucket> --json (the count and the bytes), gcloud storage buckets describe gs://<source-bucket> (versioning, retention policy, default key, requester pays, soft delete policy, storage class), and for the objects the owner names rclone lsjson --metadata SRC:<source-bucket> --files-only -R --max-depth 1. Target (after the draft is applied, the bucket exists and a key of a credentials group is issued): rclone lsd DST: and rclone size DST:<target-bucket> --json: the bucket is empty. Record the number of objects and the bytes beside the size the customer stated (the size of the data is not provided); the plan has no input for the number of objects. Check that the move host reaches both endpoints. Runbook section: terraform/handover/bucket-media/data-copy.md#preflight.
State: open input
The data preflight of google_storage_bucket.media MAN/data/google_storage_bucket.media/preflight
Open fields (10, 10 still needed)
  • copy volume: UNKNOWN — supplied by Data Architect (the amount of data of google_storage_bucket.media to copy: the used space measured on the source; the provisioned capacity of the source is not the amount of data; closed when the measured amount and the date of the measurement are recorded)
  • change rate: UNKNOWN — supplied by Data Architect (how much data the writers of google_storage_bucket.media change per hour; closed when the rate measured over a representative period is recorded, with the time a final pass needs at that rate)
  • write-freeze window: UNKNOWN — supplied by Data Architect (the window in which the writers of google_storage_bucket.media stop for the final pass; closed when the owner of the application agrees the start and the end of the window and it is recorded)
  • last sync: UNKNOWN — supplied by Data Architect (the time the final pass ends and its checks hold; closed when the time of the final pass and the result of its checks are recorded)
  • return point: UNKNOWN — supplied by Data Architect (the state of google_storage_bucket.media the migration returns to on a rollback: the source as it was at the write freeze, or a named snapshot or backup; closed when the return point is recorded with its time and how it is restored)
  • consistency check: UNKNOWN — supplied by Data Architect (how the copy of google_storage_bucket.media is shown complete and unchanged after the final pass: the used space and a checksum of the data (of the files, or the row counts of the tables) agree with the source; closed when the method is agreed and its result after the final pass is recorded)
  • validation on the target: UNKNOWN — supplied by Migration Owner (the test the application that uses google_storage_bucket.media passes on STACKIT with the copied data before the cutover, agreed with the owner of the application; closed when the test passes on the target and its result is recorded)
  • source retention: UNKNOWN — supplied by Migration Owner (google_storage_bucket.media is not retired until the owner decides to retire it; how long it and its final backup are kept after that is the owner's; closed when the date until which google_storage_bucket.media is kept is recorded)
  • rollback trigger: UNKNOWN — supplied by Migration Owner (the owner's decision to go back; the criteria that call it; closed when the criteria (which check fails, which metric passes which limit, by when) are recorded before the cutover)
  • data written to the target: UNKNOWN — supplied by Data Architect (what is written on STACKIT after the switch is not in Google Cloud: it is copied back to google_storage_bucket.media before Google Cloud serves again, or accepted as lost; closed when the choice is recorded before the cutover)
Data ArchitectHolds steps — every UNKNOWN check of the plan is HOLDS or FAILS, the number of objects and the bytes are recorded, and both buckets answer
Needs: the checks that are UNKNOWN and what closes each: target-bucket-and-credentials (closed by: preflight on the target: rclone lsd DST: and rclone size DST:<target-bucket> --json with that key (the bucket exists and is empty)); source-read-access (closed by: preflight on the source: rclone lsd SRC: and rclone size SRC:<source-bucket> --json with the identity the move host uses, and a read of a sample of the objects the owner names); and 7 more, all in the Needs of the step (execution/manual/actions.md)
Then: These can start once it is done: Rehearse the copy with a representative part of the bucket: the…
— terraform/handover/bucket-media/data-copy.md
Rehearse the copy with a representative part of the bucket: the objects of one prefix and the largest and the smallest objects, into the prefix stacktoit-rehearsal/ of the target bucket. Note the elapsed time and the bytes a second for small and for large objects, compare rclone lsjson --metadata of a sample on both sides (content type, custom metadata, storage class, modification time), and delete the prefix stacktoit-rehearsal/ when the rehearsal is done. Runbook section: terraform/handover/bucket-media/data-copy.md#rehearsal.
State: open input
The data rehearsal of google_storage_bucket.media MAN/data/google_storage_bucket.media/rehearsal
Data ArchitectHolds steps — the elapsed times are recorded, the metadata of the sample is compared and the window of the final pass is agreed from them
Needs: the customer's statements in inputs.yaml: source.dataset.size, source.dataset.bandwidth
Then: These can start once it is done: While the writers keep writing to the source, copy every live object…
— —
While the writers keep writing to the source, copy every live object to the target. The credentials of the target are the environment names TARGET_ACCESS_KEY_ID and TARGET_SECRET_ACCESS_KEY, set in the shell of the move host at run time from the credential of a credentials group; the source uses the Google identity of that shell (the service account the host runs as, or a login you made for the move; rclone's env_auth takes it from the environment). No value is written into a file, a ticket or this plan. With the remotes of the preflight: rclone copy SRC:<source-bucket> DST:<target-bucket> --s3-upload-cutoff 0 --progress --log-file=<log-file> (the form STACKIT's tutorial uses). Read the log for every error before the next step. Runbook section: terraform/handover/bucket-media/data-copy.md#initial-copy-rclone-copy.
State: can be carried out now
The initial copy of the data of google_storage_bucket.media with rclone MAN/data/google_storage_bucket.media/initial-copy/rclone-copy
Data ArchitectHolds steps — the command ends without an error and rclone size SRC:<source-bucket> --json and rclone size DST:<target-bucket> --json differ only by what was written after the copy started
Then: These can start once it is done: Run the same rclone copy again, as often as the business needs the…
— —
Run the same rclone copy again, as often as the business needs the target to be close to the source: each pass skips the objects that are identical (rclone compares size and modification time; --checksum compares size and hash where there is one, and Cloud Storage stores the MD5 natively) and copies the ones that are new or changed. It deletes nothing on the target, so an object deleted in the source stays there until the final pass. Note how many objects and bytes each pass transferred. Runbook section: terraform/handover/bucket-media/data-copy.md#delta-sync-rclone-copy.
State: open input
The replication watch of google_storage_bucket.media with rclone MAN/data/google_storage_bucket.media/delta-sync/rclone-copy
Data ArchitectHolds steps — the passes get shorter until a pass is as short as the freeze window the business accepts
Needs: the customer's statements in inputs.yaml: source.dataset.write_rate
Then: These can start once it is done: List who writes to the bucket: the units the README lists for it, and…
— —
Apply the block of terraform/data.tf with OpenTofu
State: open input
The OpenTofu step for stackit_postgresflex_instance.postgres TF/stackit_postgresflex_instance.postgres
Data ArchitectHolds steps — OpenTofu applies the blocks of terraform/data.tf and the checks of their steps in execution/verify/checks.md hold.
Needs: the variables the blocks read (terraform/variables.tf says which have no default): postgres_allowed_cidrs, postgres_storage_size, postgresflex_storage_class, project_id
Then: These can start once it is done: Close what the plan lists as UNKNOWN, from the move host, with…
terraform/data.tf
Close what the plan lists as UNKNOWN, from the move host, with read-only queries. The move host reaches the source through the connection method you already use for Cloud SQL for PostgreSQL (an authorized network of a public address, a private address inside the VPC network, or a proxy you run). Source: PGPASSWORD="$SOURCE_PGPASSWORD" PGSSLMODE=require psql --host=<source-host> --port=<source-port> --username=<source-user> --dbname=<source-db> --command='SHOW server_version;', SELECT extname, extversion FROM pg_extension ORDER BY 1;, SELECT pg_size_pretty(pg_database_size(current_database())); against the free storage of the instance (at least 25 percent of the database size free before a large export), \du and \dp for the roles and grants, and the users that sign in with an IAM identity. Target (after the draft is applied and the instance, user and database exist): PGPASSWORD="$TARGET_PGPASSWORD" PGSSLMODE=require psql --host=<target-host> --port=<target-port> --username=<target-user> --dbname=<target-db> --command='SHOW extwlist.extensions;' and SELECT version();. Check the move host is in network.acl of the instance, reaches both ends and speaks TLS 1.3. Logical replication: on the source SHOW wal_level;, SHOW max_replication_slots;, SHOW max_wal_senders; and the tables without a primary key (SELECT n.nspname, c.relname FROM pg_class c JOIN pg_namespace n ON n.oid = c.relnamespace WHERE c.relkind = 'r' AND n.nspname NOT IN ('pg_catalog', 'information_schema') AND NOT EXISTS (SELECT 1 FROM pg_index i WHERE i.indrelid = c.oid AND i.indisprimary);); on the empty target the probe CREATE SUBSCRIPTION stacktoit_probe CONNECTION 'host=localhost dbname=x' PUBLICATION p WITH (connect = false); then ALTER SUBSCRIPTION stacktoit_probe SET (slot_name = NONE); and DROP SUBSCRIPTION stacktoit_probe;. Runbook section: terraform/handover/database-postgres/data-move.md#preflight.
State: open input
The data preflight of google_sql_database_instance.postgres MAN/data/google_sql_database_instance.postgres/preflight
Open fields (10, 10 still needed)
  • copy volume: UNKNOWN — supplied by Data Architect (the amount of data of google_sql_database_instance.postgres to copy: the used space measured on the source; the provisioned capacity of the source is not the amount of data; closed when the measured amount and the date of the measurement are recorded)
  • change rate: UNKNOWN — supplied by Data Architect (how much data the writers of google_sql_database_instance.postgres change per hour; closed when the rate measured over a representative period is recorded, with the time a final pass needs at that rate)
  • write-freeze window: UNKNOWN — supplied by Data Architect (the window in which the writers of google_sql_database_instance.postgres stop for the final pass; closed when the owner of the application agrees the start and the end of the window and it is recorded)
  • last sync: UNKNOWN — supplied by Data Architect (the time the final pass ends and its checks hold; closed when the time of the final pass and the result of its checks are recorded)
  • return point: UNKNOWN — supplied by Data Architect (the state of google_sql_database_instance.postgres the migration returns to on a rollback: the source as it was at the write freeze, or a named snapshot or backup; closed when the return point is recorded with its time and how it is restored)
  • consistency check: UNKNOWN — supplied by Data Architect (how the copy of google_sql_database_instance.postgres is shown complete and unchanged after the final pass: the used space and a checksum of the data (of the files, or the row counts of the tables) agree with the source; closed when the method is agreed and its result after the final pass is recorded)
  • validation on the target: UNKNOWN — supplied by Migration Owner (the test the application that uses google_sql_database_instance.postgres passes on STACKIT with the copied data before the cutover, agreed with the owner of the application; closed when the test passes on the target and its result is recorded)
  • source retention: UNKNOWN — supplied by Migration Owner (google_sql_database_instance.postgres is not retired until the owner decides to retire it; how long it and its final backup are kept after that is the owner's; closed when the date until which google_sql_database_instance.postgres is kept is recorded)
  • rollback trigger: UNKNOWN — supplied by Migration Owner (the owner's decision to go back; the criteria that call it; closed when the criteria (which check fails, which metric passes which limit, by when) are recorded before the cutover)
  • data written to the target: UNKNOWN — supplied by Data Architect (what is written on STACKIT after the switch is not in Google Cloud: it is copied back to google_sql_database_instance.postgres before Google Cloud serves again, or accepted as lost; closed when the choice is recorded before the cutover)
Data ArchitectHolds steps — every UNKNOWN check of the plan is HOLDS or FAILS; the extension list of the source is compared with SHOW extwlist.extensions; of the target and each difference is settled
Needs: the checks that are UNKNOWN and what closes each: extensions (closed by: preflight: on the source SELECT extname, extversion FROM pg_extension ORDER BY 1; on the target SHOW extwlist.extensions; and trust the target); and 10 more, all in the Needs of the step (execution/manual/actions.md)
Then: These can start once it is done: Rehearse the chosen method into a scratch database of the target…
— terraform/handover/database-postgres/data-move.md
Rehearse the chosen method into a scratch database of the target (a second stackit_postgresflex_database or a clone of the instance) from a copy of the source (a clone or a restored backup of the Cloud SQL for PostgreSQL instance, so that production is not loaded). Note the elapsed time of the dump, the restore, the index build and the verification. Drop the scratch database and the copy afterwards. Runbook section: terraform/handover/database-postgres/data-move.md#rehearsal.
State: open input
The data rehearsal of google_sql_database_instance.postgres MAN/data/google_sql_database_instance.postgres/rehearsal
Data ArchitectHolds steps — the elapsed times of each part are recorded and the write-freeze window is agreed from them
Needs: the customer's statements in inputs.yaml: source.dataset.size, source.dataset.bandwidth
Then: Brings closer once it is done (each waits for more): Source: turn logical decoding on: set the flag… and 1 more.
— —
Source: turn logical decoding on: set the flag cloudsql.logical_decoding to on on the instance (a restart of the instance), create a user for the publication with the REPLICATION attribute that holds CREATE on the database (CREATE ROLE stacktoit_repl WITH LOGIN REPLICATION PASSWORD '<replication-password>';, typed in an interactive session). Every table needs a primary key or a replica identity. Copy the schema (no later DDL on either side): PGPASSWORD="$SOURCE_PGPASSWORD" pg_dump --schema-only --no-owner --no-acl --host=<source-host> --port=<source-port> --username=<source-user> --dbname=<source-db> | PGPASSWORD="$TARGET_PGPASSWORD" PGSSLMODE=require psql --host=<target-host> --port=<target-port> --username=<target-user> --dbname=<target-db>. Publish on the source: CREATE PUBLICATION stacktoit_move FOR ALL TABLES;. Subscribe on the target in an interactive psql session so that no password is stored in a file or the shell history: CREATE SUBSCRIPTION stacktoit_move CONNECTION 'host=<source-host> port=<source-port> dbname=<source-db> user=stacktoit_repl password=<replication-password> sslmode=require' PUBLICATION stacktoit_move;. Wait until SELECT srrelid::regclass, srsubstate FROM pg_subscription_rel; shows r for every table. Runbook section: terraform/handover/database-postgres/data-move.md#initial-copy-logical-replication.
State: waits for decisions
The initial copy of the data of google_sql_database_instance.postgres by logical replication MAN/data/google_sql_database_instance.postgres/initial-copy/logical-replication
Data ArchitectHolds steps DEC-GEN-CONVERT-DATA-MOVEMENT every table of the target is in state r and the replication slot of the source is active
Needs: the answer of DEC-GEN-CONVERT-DATA-MOVEMENT in decisions.yaml, which names the path this step belongs to
Then: Brings closer once it is done (each waits for more): Keep the target apart: the application does not write to it and no…
— —
Keep the target apart: the application does not write to it and no DDL runs on either side. Watch the lag and the free storage of the source: SELECT slot_name, active, pg_size_pretty(pg_wal_lsn_diff(pg_current_wal_lsn(), confirmed_flush_lsn)) AS lag FROM pg_replication_slots;. Runbook section: terraform/handover/database-postgres/data-move.md#delta-sync-logical-replication.
State: waits for decisions
The replication watch of google_sql_database_instance.postgres by logical replication MAN/data/google_sql_database_instance.postgres/delta-sync/logical-replication
Data ArchitectHolds steps DEC-GEN-CONVERT-DATA-MOVEMENT the lag stays bounded and the free storage of the source does not fall
Needs: the customer's statements in inputs.yaml: source.dataset.write_rate
Then: Brings closer once it is done (each waits for more): List who writes (`SELECT usename, application_name, client_addr…
— —
Declare the topics and subscriptions of the source on the RabbitMQ instance (exchanges: 1, queues: 0): run rabbitmq/apply-topology.sh, which writes rabbitmq/topology.json through the HTTP API of the broker. Nothing of this was run on STACKIT, and whether the credential may declare them is not stated: the script asks first and stops with the answer
State: open input
The step "Declare the topics and subscriptions of the source on the RabbitMQ instance" MAN/rabbitmq/topology
Platform EngineerLater — the script ends with status 0 after reading every queue back
Needs: a credential of the instance (stackit_rabbitmq_credential): its http_api_uri (RABBITMQ_HTTP_API_URI), username and password (RABBITMQ_USERNAME, RABBITMQ_PASSWORD), and the virtual host of its uri (RABBITMQ_VHOST)
Then: No other job on the board waits for it.
— —
Apply the block of terraform/messaging.tf with OpenTofu
State: open input
The OpenTofu step for stackit_rabbitmq_instance.messaging TF/stackit_rabbitmq_instance.messaging
Platform ArchitectLater — OpenTofu applies the blocks of terraform/messaging.tf and the checks of their steps in execution/verify/checks.md hold.
Needs: the variables the blocks read (terraform/variables.tf says which have no default): project_id, rabbitmq_allowed_cidrs, rabbitmq_plan_name, rabbitmq_version
Then: No other job on the board waits for it.
terraform/messaging.tf
Apply the block of terraform/kubernetes.tf with OpenTofu
State: open input
The OpenTofu step for stackit_ske_cluster.containers TF/stackit_ske_cluster.containers
Platform ArchitectHolds steps — OpenTofu applies the blocks of terraform/kubernetes.tf and the checks of their steps in execution/verify/checks.md hold.
Needs: the variables the blocks read (terraform/variables.tf says which have no default): availability_zones, containers_machine_type, containers_nodes_max, containers_nodes_min, project_id
Then: These can start once it is done: Fetch the kubeconfig, check the health, create the namespace and the…
terraform/kubernetes.tf
Fetch the kubeconfig, check the health, create the namespace and the secrets of the SKE cluster(s) of the draft: the namespace is one you choose for all manifest files, the secrets are migrate-secrets, server-secrets (the keys of each are listed under SECRETS TO CREATE in the header of its manifest file)
State: open input
The step "Fetch the kubeconfig, check the health, create the namespace and the secrets of…" MAN/draft/handover/cluster-access/kubeconfig-md
Platform ArchitectHolds steps — the kubeconfig of each cluster of terraform/handover/cluster-access/kubeconfig.md is fetched, each cluster passes its health verification, the namespace exists and the secrets the headers of the manifest files list are created (steps 1 to 5 of the document); applying the manifest files and their cutover (steps 6 and 7) are the steps of those files in the plan
Needs: the STACKIT project id and a login of the STACKIT CLI for that project, and the name of each cluster (the table of handover/cluster-access/kubeconfig.md); the name of the namespace, which the source does not state, so you choose it once for all manifest files (they are applied into it with -n); and 2 more, all in the Needs of the step (execution/manual/actions.md)
Then: Brings closer once it is done (each waits for more): Review the critical settings of a Cloud Run service… and 1 more.
— terraform/handover/cluster-access/kubeconfig.md
Fill in the required inputs of kubernetes/server/manifests.yaml and apply it to the cluster stackit_ske_cluster.containers (put 0 in the number of pods): kubectl apply -n <namespace> -f <manifest file>; no pod starts. The pods start when the data they connect to is moved, by the person who runs the cutover (step 2 of the header)
State: can be carried out now
The step "Fill in the required inputs of kubernetes/server/manifests.yaml and apply it to…" MAN/draft/kubernetes/server/manifests-yaml
Platform ArchitectLater — every manifest of terraform/kubernetes/server/manifests.yaml is applied to the cluster with its inputs filled in and no pod running, and the Cloud Run resource still runs
Then: No other job on the board waits for it.
— terraform/kubernetes/server/manifests.yaml
List who writes (SELECT usename, application_name, client_addr, count(*) FROM pg_stat_activity WHERE datname = '<source-db>' GROUP BY 1, 2, 3 ORDER BY 4 DESC;) and record the connection settings of every client where they can be restored from. Then stop the writers at the application (services, jobs, migrations, cron). Do not make the source read-only and do not change it. Check: SELECT count(*) FROM pg_stat_activity WHERE datname = '<source-db>' AND state <> 'idle' AND pid <> pg_backend_pid(); is 0. Runbook section: terraform/handover/database-postgres/data-move.md#write-freeze-dump-restore.
State: waits for decisions
The write freeze of google_sql_database_instance.postgres by dump and restore MAN/data/google_sql_database_instance.postgres/write-freeze/dump-restore
Migration OwnerHolds steps DEC-GEN-CONVERT-DATA-MOVEMENT no client writes to the source
Needs: the customer's statements in inputs.yaml: source.dataset.downtime; the maintenance window is not given: the plan states none and invents none; state the window, the blackout days and the longest downtime of one switch with ops.maintenance_window in the inputs file (inputs-template.yaml shows the empty answer), then run again
Then: Brings closer once it is done (each waits for more): Dump inside the freeze: `PGPASSWORD="$SOURCE_PGPASSWORD"…
— —
Dump inside the freeze: PGPASSWORD="$SOURCE_PGPASSWORD" PGSSLMODE=require pg_dump --host=<source-host> --port=<source-port> --username=<source-user> --dbname=<source-db> --format=directory --jobs=4 --no-owner --no-acl --file=<dump-dir> (Google's page names --no-owner and --no-acl for a dump of one database and the directory format for a parallel dump; dump one database at a time, since pg_dumpall fails for databases with several owners). Restore as the database owner into the empty database: PGPASSWORD="$TARGET_PGPASSWORD" PGSSLMODE=require pg_restore --host=<target-host> --port=<target-port> --username=<target-user> --dbname=<target-db> --jobs=4 --no-owner --no-acl <dump-dir> 2> restore.log, then read restore.log line by line; create the extensions of the source that the target lists and settle the ones it does not. Runbook section: terraform/handover/database-postgres/data-move.md#final-sync-dump-restore.
State: waits for decisions
The final copy of the data of google_sql_database_instance.postgres by dump and restore MAN/data/google_sql_database_instance.postgres/final-sync/dump-restore
Data ArchitectHolds steps DEC-GEN-CONVERT-DATA-MOVEMENT pg_restore finished and every error in restore.log is settled
Needs: the customer's statements in inputs.yaml: source.dataset.downtime; the maintenance window is not given: the plan states none and invents none; state the window, the blackout days and the longest downtime of one switch with ops.maintenance_window in the inputs file (inputs-template.yaml shows the empty answer), then run again
Then: Brings closer once it is done (each waits for more): Both sides, with the writers stopped: per-table counts…
— —
Both sides, with the writers stopped: per-table counts (SELECT format('SELECT %L AS tbl, count(*) FROM %I.%I;', schemaname || '.' || tablename, schemaname, tablename) FROM pg_tables WHERE schemaname NOT IN ('pg_catalog', 'information_schema'); run on each side), an md5 of every keyed table (SELECT count(*), md5(string_agg(t::text, ',' ORDER BY t.<key-column>)) FROM <schema>.<table> t;, a key range for a large table, DateStyle, TimeZone and extra_float_digits equal in both sessions), the sequences, and one read query the application itself runs on its most important data, <application-query>: the query and the answer are the customer's, the source does not state them. Record GO or NO-GO. Runbook section: terraform/handover/database-postgres/data-move.md#reconcile-dump-restore.
State: waits for decisions
The data reconciliation of google_sql_database_instance.postgres by dump and restore MAN/data/google_sql_database_instance.postgres/reconcile/dump-restore
Data ArchitectHolds steps DEC-GEN-CONVERT-DATA-MOVEMENT counts, checksums, sequences and the application query agree: GO
Needs: the answer of DEC-GEN-CONVERT-DATA-MOVEMENT in decisions.yaml, which names the path this step belongs to
Then: Brings closer once it is done (each waits for more): Only after the target has run in production for the period the…
— —
List who writes (SELECT usename, application_name, client_addr, count(*) FROM pg_stat_activity WHERE datname = '<source-db>' GROUP BY 1, 2, 3 ORDER BY 4 DESC;) and record the connection settings of every client where they can be restored from. Then stop the writers at the application (services, jobs, migrations, cron). Do not make the source read-only and do not change it. Check: SELECT count(*) FROM pg_stat_activity WHERE datname = '<source-db>' AND state <> 'idle' AND pid <> pg_backend_pid(); is 0. Runbook section: terraform/handover/database-postgres/data-move.md#write-freeze-logical-replication.
State: waits for decisions
The write freeze of google_sql_database_instance.postgres by logical replication MAN/data/google_sql_database_instance.postgres/write-freeze/logical-replication
Migration OwnerHolds steps DEC-GEN-CONVERT-DATA-MOVEMENT no client writes to the source
Needs: the customer's statements in inputs.yaml: source.dataset.downtime; the maintenance window is not given: the plan states none and invents none; state the window, the blackout days and the longest downtime of one switch with ops.maintenance_window in the inputs file (inputs-template.yaml shows the empty answer), then run again
Then: Brings closer once it is done (each waits for more): Wait until the lag is 0.
— —
Wait until the lag is 0. Copy the sequences: on the source SELECT format('SELECT setval(%L, %s);', schemaname || '.' || sequencename, last_value) FROM pg_sequences WHERE last_value IS NOT NULL; with psql --tuples-only --no-align, and run the output on the target. Then disable the subscription on the target: ALTER SUBSCRIPTION stacktoit_move DISABLE; (the slot stays on the source, so the way back stays open). Runbook section: terraform/handover/database-postgres/data-move.md#final-sync-logical-replication.
State: waits for decisions
The final copy of the data of google_sql_database_instance.postgres by logical replication MAN/data/google_sql_database_instance.postgres/final-sync/logical-replication
Data ArchitectHolds steps DEC-GEN-CONVERT-DATA-MOVEMENT the lag was 0, the sequences on the target are not lower than the source's, the subscription is disabled
Needs: the customer's statements in inputs.yaml: source.dataset.downtime; the maintenance window is not given: the plan states none and invents none; state the window, the blackout days and the longest downtime of one switch with ops.maintenance_window in the inputs file (inputs-template.yaml shows the empty answer), then run again
Then: Brings closer once it is done (each waits for more): Both sides, with the writers stopped: per-table counts…
— —
Both sides, with the writers stopped: per-table counts (SELECT format('SELECT %L AS tbl, count(*) FROM %I.%I;', schemaname || '.' || tablename, schemaname, tablename) FROM pg_tables WHERE schemaname NOT IN ('pg_catalog', 'information_schema'); run on each side), an md5 of every keyed table (SELECT count(*), md5(string_agg(t::text, ',' ORDER BY t.<key-column>)) FROM <schema>.<table> t;, a key range for a large table, DateStyle, TimeZone and extra_float_digits equal in both sessions), the sequences, and one read query the application itself runs on its most important data, <application-query>: the query and the answer are the customer's, the source does not state them. Record GO or NO-GO. Runbook section: terraform/handover/database-postgres/data-move.md#reconcile-logical-replication.
State: waits for decisions
The data reconciliation of google_sql_database_instance.postgres by logical replication MAN/data/google_sql_database_instance.postgres/reconcile/logical-replication
Data ArchitectHolds steps DEC-GEN-CONVERT-DATA-MOVEMENT counts, checksums, sequences and the application query agree: GO
Needs: the answer of DEC-GEN-CONVERT-DATA-MOVEMENT in decisions.yaml, which names the path this step belongs to
Then: Brings closer once it is done (each waits for more): Only after the target has run in production for the period the…
— —
List who writes (SELECT usename, application_name, client_addr, count(*) FROM pg_stat_activity WHERE datname = '<source-db>' GROUP BY 1, 2, 3 ORDER BY 4 DESC;) and record the connection settings of every client where they can be restored from. Then stop the writers at the application (services, jobs, migrations, cron). Do not make the source read-only and do not change it. Check: SELECT count(*) FROM pg_stat_activity WHERE datname = '<source-db>' AND state <> 'idle' AND pid <> pg_backend_pid(); is 0. Runbook section: terraform/handover/database-postgres/data-move.md#write-freeze-own-tool.
State: waits for decisions
The write freeze of google_sql_database_instance.postgres with a tool of your own MAN/data/google_sql_database_instance.postgres/write-freeze/own-tool
Migration OwnerHolds steps DEC-GEN-CONVERT-DATA-MOVEMENT no client writes to the source
Needs: the customer's statements in inputs.yaml: source.dataset.downtime; the maintenance window is not given: the plan states none and invents none; state the window, the blackout days and the longest downtime of one switch with ops.maintenance_window in the inputs file (inputs-template.yaml shows the empty answer), then run again
Then: Brings closer once it is done (each waits for more): Copy the data of google_sql_database_instance.postgres to…
— —
Copy the data of google_sql_database_instance.postgres to stackit_postgresflex_instance.postgres with the migration tool or the replication you chose: write its steps, the checks before the move, the freeze window it needs and the way back. Runbook section: terraform/handover/database-postgres/data-move.md#final-sync-own-tool.
State: waits for decisions
The final copy of the data of google_sql_database_instance.postgres with a tool of your own MAN/data/google_sql_database_instance.postgres/final-sync/own-tool
Data ArchitectHolds steps DEC-GEN-CONVERT-DATA-MOVEMENT the data of google_sql_database_instance.postgres is in stackit_postgresflex_instance.postgres and the checks of the tool hold
Needs: the tool, its steps, the checks before the move, the freeze window and the way back, from the person who runs it; the maintenance window is not given: the plan states none and invents none; state the window, the blackout days and the longest downtime of one switch with ops.maintenance_window in the inputs file (inputs-template.yaml shows the empty answer), then run again
Then: Brings closer once it is done (each waits for more): Both sides, with the writers stopped: per-table counts…
— —
Both sides, with the writers stopped: per-table counts (SELECT format('SELECT %L AS tbl, count(*) FROM %I.%I;', schemaname || '.' || tablename, schemaname, tablename) FROM pg_tables WHERE schemaname NOT IN ('pg_catalog', 'information_schema'); run on each side), an md5 of every keyed table (SELECT count(*), md5(string_agg(t::text, ',' ORDER BY t.<key-column>)) FROM <schema>.<table> t;, a key range for a large table, DateStyle, TimeZone and extra_float_digits equal in both sessions), the sequences, and one read query the application itself runs on its most important data, <application-query>: the query and the answer are the customer's, the source does not state them. Record GO or NO-GO. Runbook section: terraform/handover/database-postgres/data-move.md#reconcile-own-tool.
State: waits for decisions
The data reconciliation of google_sql_database_instance.postgres with a tool of your own MAN/data/google_sql_database_instance.postgres/reconcile/own-tool
Data ArchitectLater DEC-GEN-CONVERT-DATA-MOVEMENT counts, checksums, sequences and the application query agree: GO
Needs: the answer of DEC-GEN-CONVERT-DATA-MOVEMENT in decisions.yaml, which names the path this step belongs to
Then: No other job on the board waits for it.
— —
List who writes to the bucket: the units the README lists for it, and every job, partner and signed URL outside the scan (if Cloud Audit Logs record data writes for the bucket, its object writes and deletes name the principals; the Terraform does not show whether they are). Record the endpoint, the bucket name and the credential settings of every client where they can be restored from. Then stop the writers at the application (services, jobs, uploads). Do not change the source bucket (no read-only policy, no retention lock): it stays read-write, so the way back needs nothing on the source. Runbook section: terraform/handover/bucket-media/data-copy.md#write-freeze-rclone-copy.
State: open input
The write freeze of google_storage_bucket.media with rclone MAN/data/google_storage_bucket.media/write-freeze/rclone-copy
Migration OwnerHolds steps — no client writes to the source
Needs: the customer's statements in inputs.yaml: source.dataset.downtime; the maintenance window is not given: the plan states none and invents none; state the window, the blackout days and the longest downtime of one switch with ops.maintenance_window in the inputs file (inputs-template.yaml shows the empty answer), then run again
Then: These can start once it is done: Inside the freeze run the rclone copy of the initial copy once more…
— —
Inside the freeze run the rclone copy of the initial copy once more and read how many objects it transferred; run it a second time: it transfers nothing. Then see what the target holds that the source no longer has: rclone sync SRC:<source-bucket> DST:<target-bucket> --dry-run prints what a sync would delete; read the list, and only a person who has read it runs the sync without --dry-run (the target must equal the source at the cutover, and an object deleted in the source after the initial copy is otherwise still served). Runbook section: terraform/handover/bucket-media/data-copy.md#final-sync-rclone-copy.
State: open input
The final copy of the data of google_storage_bucket.media with rclone MAN/data/google_storage_bucket.media/final-sync/rclone-copy
Data ArchitectHolds steps — the second pass transfers nothing and every object that exists only on the target is settled
Needs: the customer's statements in inputs.yaml: source.dataset.downtime; the maintenance window is not given: the plan states none and invents none; state the window, the blackout days and the longest downtime of one switch with ops.maintenance_window in the inputs file (inputs-template.yaml shows the empty answer), then run again
Then: These can start once it is done: Both sides, with the writers stopped: the number of objects and the…
— —
Both sides, with the writers stopped: the number of objects and the bytes (rclone size SRC:<source-bucket> --json, rclone size DST:<target-bucket> --json); the list of keys (rclone lsf -R --files-only SRC:<source-bucket> | sort > source-keys.txt, the same for the target, diff source-keys.txt target-keys.txt is empty); and the content: rclone check SRC:<source-bucket> DST:<target-bucket> --one-way --combined=<check-file> compares size and hash where both sides have one and marks every difference, so read the file and the log; an object for which the two sides share no hash (the target's ETag of a multipart upload is not an MD5) is at best compared by size, which is not its content, so run rclone check ... --download for the prefixes that matter and for a sample of the rest. One read that the application itself does on its most important objects through the STACKIT endpoint with a key of a credentials group: <application-read>, the query and the answer are the customer's, the source does not state them. Record GO or NO-GO. Runbook section: terraform/handover/bucket-media/data-copy.md#reconcile-rclone-copy.
State: can be carried out now
The data reconciliation of google_storage_bucket.media with rclone MAN/data/google_storage_bucket.media/reconcile/rclone-copy
Data ArchitectHolds steps — the counts, the key lists and the checks agree, the application read works: GO
Then: These can start once it is done: Only after the target has run in production for the period the…
— —
Only after the target has run in production for the period the customer decides and the way back is no longer wanted: remove the move host from network.acl of the instance and from the authorized networks of the source if it was added; delete the dump files and restore.log; keep a final backup of the source for the retention the customer decides before anything is deleted; replace the credentials of the target user if they were ever on a ticket or in a file. Runbook section: terraform/handover/database-postgres/data-move.md#clean-up-dump-restore.
State: waits for decisions
The cleanup of the data move of google_sql_database_instance.postgres by dump and restore MAN/data/google_sql_database_instance.postgres/cleanup/dump-restore
Data ArchitectLater DEC-GEN-CONVERT-DATA-MOVEMENT no slot, subscription, publication or dump file is left, the move host is out of every access list, the credentials are replaced
Needs: the answer of DEC-GEN-CONVERT-DATA-MOVEMENT in decisions.yaml, which names the path this step belongs to
Then: No other job on the board waits for it.
— —
Only after the target has run in production for the period the customer decides and the way back is no longer wanted: DROP SUBSCRIPTION stacktoit_move; on the target (it drops the slot on the source if the source is reachable; check SELECT * FROM pg_replication_slots;), DROP PUBLICATION stacktoit_move; and DROP ROLE stacktoit_repl; on the source, set cloudsql.logical_decoding back with a second restart if it was off before the move; remove the move host from network.acl of the instance and from the authorized networks of the source if it was added; delete the dump files and restore.log; keep a final backup of the source for the retention the customer decides before anything is deleted; replace the credentials of the target user if they were ever on a ticket or in a file. Runbook section: terraform/handover/database-postgres/data-move.md#clean-up-logical-replication.
State: waits for decisions
The cleanup of the data move of google_sql_database_instance.postgres by logical replication MAN/data/google_sql_database_instance.postgres/cleanup/logical-replication
Data ArchitectLater DEC-GEN-CONVERT-DATA-MOVEMENT no slot, subscription, publication or dump file is left, the move host is out of every access list, the credentials are replaced
Needs: the answer of DEC-GEN-CONVERT-DATA-MOVEMENT in decisions.yaml, which names the path this step belongs to
Then: No other job on the board waits for it.
— —
Only after the target has run in production for the period the customer decides and the way back is no longer wanted: delete the key lists and the logs of the move (they name every object key); delete the credential made for the move, the Google login or key made for it, and take the environment names out of the shell history; keep the source bucket, with its versions, for the retention the customer decides before any object of it is deleted, and do not delete it in the same hour as the cutover. Runbook section: terraform/handover/bucket-media/data-copy.md#clean-up-rclone-copy.
State: can be carried out now
The cleanup of the data move of google_storage_bucket.media with rclone MAN/data/google_storage_bucket.media/cleanup/rclone-copy
Data ArchitectLater — no key list or log is left, the credentials of the move are removed, and the retention of the source is recorded
Then: No other job on the board waits for it.
— —

Verify (0 jobs)

No job in this queue.