Newer
Older
openstack-caracal-ipv4 / clientdocs / ci-integration-guide.md

Omega Cloud -- CI/Automation Integration Guide (TEMPLATE)

TEMPLATE NOTE (removed before delivery): fields written as {{THIS}} are filled in by us per client; fields marked "you fill" come from the credential files delivered to your custodians and are entered by you, on your side, into your CI system's secret store.

How to connect a CI system (Jenkins, GitLab CI, GitHub Actions, or plain scripts) to your Omega Cloud environment. Read the Handover Pack first -- sections 4 (credential handling) and 6 (boundary items) are assumed here.

1. The one rule: pipelines use the application credential

All automation authenticates as the {{TENANT_SHORT_NAME}}-svc account's application credential ({{TENANT_SHORT_NAME}}-svc-cred). Never a password. Why this pattern:

  • Scoped: it acts only inside your project, with exactly the rights of the -svc account (member + load-balancer_member). It cannot touch identity (users, roles), quotas, or anything outside your domain -- so a leaked pipeline credential is contained by design.
  • Revocable without collateral: delete the application credential and every pipeline using it stops -- but the -svc account, its password, and your other credentials are untouched. Rotations never require us.
  • No interactive dependency: it does not expire with a password change.

The corollary boundaries (platform-enforced, not policy suggestions):

  • The application credential cannot create or delete Kubernetes clusters (section 5 below).
  • It cannot create users, grant roles, or change quotas. Pipelines that try will get a permission error -- that error is correct behavior.

2. Storing the credential in your CI system

You received the credential's id and secret in the delivered file {{TENANT_SHORT_NAME}}-svc-appcred.txt. Put both into your CI system's native secret store (in Jenkins: Manage Jenkins > Credentials, as "secret text" entries or a username/password pair), then inject them into jobs as environment variables. Never:

  • commit them to a repository (including a private one),
  • bake them into a container or VM image,
  • echo them in build output (mask them in your CI configuration).

3. clouds.yaml for pipelines

The OpenStack CLI and SDKs read clouds.yaml. A working template -- also delivered ready to copy as scripts/clouds.yaml.template in your starter kit -- values in angle brackets are yours to fill from the delivered credential file, and the secret should be injected at job runtime, not written to disk in a repository:

clouds:
  {{TENANT_SHORT_NAME}}:
    auth_type: v3applicationcredential
    auth:
      auth_url: {{AUTH_URL}}
      application_credential_id: <id from the delivered credential file>
      application_credential_secret: <injected from your CI secret store>
    region_name: {{REGION}}
    identity_api_version: 3
    cacert: <path to the delivered CA bundle {{CA_BUNDLE_FILE}}>

Then in a pipeline step:

export OS_CLOUD={{TENANT_SHORT_NAME}}
openstack token issue

A token comes back scoped to your project; that is your smoke test. The starter-kit script scripts/smoke-test.sh wraps this (token, catalog, quota) as one pipeline-ready step, and scripts/Jenkinsfile.example shows a full Jenkins pipeline built this way. Equivalent environment-variable form (no clouds.yaml file needed):

export OS_AUTH_TYPE=v3applicationcredential
export OS_AUTH_URL={{AUTH_URL}}
export OS_IDENTITY_API_VERSION=3
export OS_CACERT=<path to the delivered CA bundle>
export OS_APPLICATION_CREDENTIAL_ID=<id>
export OS_APPLICATION_CREDENTIAL_SECRET=<from your secret store>

The same values work for Terraform/OpenTofu's OpenStack provider, Ansible's openstack.cloud collection, and the OpenStack SDK -- they all understand clouds.yaml and the OS_* variables. Do not hardcode service endpoint URLs anywhere: authenticate against {{AUTH_URL}} and let the client library discover the rest from the service catalog (openstack catalog list shows what it sees).

4. Least privilege: mint narrower credentials per pipeline

Your handover credential is intentionally capable (it can do everything the -svc account can). For production-grade hygiene, use it only as the "root" automation credential and mint narrower ones per pipeline: sign in as {{TENANT_SHORT_NAME}}-svc (password, interactively -- not from CI) and create additional application credentials with an expiry date and, where useful, a reduced role list:

openstack application credential create pipeline-nightly \
  --role member --expiration 2027-01-01T00:00:00

Give each pipeline its own credential so you can revoke one without stopping the others, and so your audit trail says which pipeline did what. Deleting a credential is immediate and self-service:

openstack application credential delete pipeline-nightly

5. Kubernetes clusters and CI

The platform's cluster machinery requires a password login (-cluster account); an application credential cannot create or delete clusters. This shapes the recommended CI pattern:

  • Recommended: create long-lived clusters manually (or on a controlled schedule) as {{TENANT_SHORT_NAME}}-cluster, outside CI. Pipelines then deploy INTO the cluster using its kubeconfig, stored in your CI secret store like any other credential.
  • Not recommended: putting the -cluster password into CI so pipelines can create clusters. If your workflow genuinely needs cluster-per-run, raise it with your account contact first -- there are capacity and quota implications too.

Everything else in this guide (networks, VMs, volumes, load balancers, secrets, floating IPs) is fully pipeline-drivable with the application credential.

6. Quota and pacing expectations

  • Your quota is the hard envelope. Every create call is checked against it server-side. Pipelines must treat quota-exceeded errors as expected, actionable failures (clean up leaked resources, or request a raise via an authorized requester) -- not as retryable platform faults. openstack quota show and openstack limits show --absolute report your envelope and current consumption; a pre-flight check in long pipelines is cheap insurance.
  • Pace your polling. Waiting on a server to go ACTIVE or a load balancer to go ONLINE should poll at 10-second intervals or slower (or use the CLI --wait flags, which do this for you). Tight polling loops add load and gain nothing.
  • Serialize heavyweight creates. Load balancers and Kubernetes clusters take minutes to build; launching many concurrently mostly makes them queue. Prefer sequential creation with waits.
  • Clean up what you create. Tag or name every pipeline-created resource with the job/build id (for example ci-{{TENANT_SHORT_NAME}}-build123-web) and make teardown a step that runs on failure too. A periodic sweep job that deletes resources older than your longest pipeline is the cheapest way to keep quota headroom. Floating IPs count against quota even when detached -- release them. The starter-kit script scripts/ci-cleanup-sweep.sh implements exactly this sweep (dry-run by default; it deletes nothing without --apply).

7. The worked sequence your pipelines should exercise

This is the canonical order of operations for an infrastructure pipeline on this platform -- the same order the Acceptance Checklist tests. Each step lists the surface it proves. Names below use a ci- prefix; substitute your build id convention.

  1. Authenticate + discover -- openstack token issue, then openstack catalog list. Proves credential and endpoint discovery.
  2. Network build-out -- create network, subnet (any private range that does not collide with {{TENANT_SHORT_NAME}}-subnet or your other networks), router with gateway to provider-ext, attach subnet. Or reuse the handover network for simple runs. Proves networking self-service.
  3. Security group -- create a group and rules for exactly the ports the deployment needs. Proves firewall self-service.
  4. Compute -- boot a server from a shared base image on your network with your keypair; wait for ACTIVE. Proves compute + image access.
  5. Block storage -- create a volume, attach it to the server, verify it is in-use, detach. Proves the storage path end to end.
  6. Public access -- allocate a floating IP from provider-ext, attach it, verify reachability (for example SSH or your app's health port). Proves the north-south path.
  7. Load balancer -- create a load balancer on your subnet with a listener, pool, and the server as a member; wait for ACTIVE/ONLINE. Proves the load-balancing service (your accounts already hold the required role).
  8. Secrets -- store, retrieve, and delete a test secret (this is also where TLS certificates for load balancer listeners live). Proves the secrets service.
  9. Teardown in reverse order -- member/pool/listener/load balancer, floating IP (release it), server, volume, security group, router interface/router/subnet/network. Verify with the corresponding list commands that nothing is left. Proves your cleanup discipline and returns your quota.

Run the full sequence once at onboarding (that is the Acceptance Checklist; the starter-kit script scripts/acceptance-run.sh automates its self-service rows) and keep a trimmed version as your pipeline's recurring smoke test.

8. When a pipeline call fails

  1. Re-run openstack token issue -- authentication failures explain most sudden breakage (revoked/expired credential, missing CA bundle in the job environment).
  2. Check quota (openstack limits show --absolute) -- the second most common cause.
  3. A permission error on identity, quota, or cluster operations is the platform working as designed (sections 1 and 5), not an outage.
  4. Anything else that looks like a platform fault: capture the exact command and the exact error text and send them to {{ACCOUNT_CONTACT}}. Verbatim errors get fast answers; paraphrased ones do not.