Repository navigation
Releases: ataila/terraform-provider-ataila
Release list
v1.2.0
A minor release: additions only, under the stability promise of 1.0.0. A configuration and a state of 1.1.0
plan with no changes.
Added
ataila_tenant_quotaresource: a tenant's whole quota set,quota= map of dimension (vcpu,ram_gb,
disk_gb,desktops,vms,ai_tpm,ai_budget_eur_month,gpu) to{limit, policy, note}(policy
autoby default,approve_alwaysorhard_cap), throughGET/PUT /tenants/{id}/quotas. The resource
owns the set the way the API replaces it: a dimension with a limit on the platform that the configuration
leaves out loses its limit on the next apply (no limit: every order touching it goes to an approval card), and
the plan warns, naming it.usage(every dimension: limit, policy, allocated, reserved, remaining),notes
andwarningsare read back. The platform keeps four decimal places; the state keeps the configuration's
spelling of a limit it rounded. Destroy removes every limit (not gated: the platform treats it as a quota
change); import by the tenant's id;tenant_idforces a new resource. A tenant that does not exist, a token
withoutorders-admin-globaland a platform without the endpoints are explained errors.ataila_tenant_quotadata source: the same set withset_byandset_atper limit,usageandnotes.ataila_catalogue_itemsdata source: the enabled catalogue items in display order — key, kind, name, edition,
requires_approval,sort_order, and the order form, quota mapping and price basis as JSON text
(spec_schema_json,quota_dimensions_json,price_hint_json).ataila_ordersdata source (tenant_id, optionalstatus) andataila_orderdata source (id, with
events): a tenant's orders, read only — approval, rejection and re-runs stay in the portal, and there is
no order resource. Each order carries its status, the quota check'squota_resultandquota_decision, who
approved or rejected it and why,operation_id, and for an AI gateway key order the delivered key'skey_id
andkey_alias(never its value); its spec, quota check, overage and delivery facts are JSON text.ataila_ai_rate_cardresource: the list rate of one serving tier,eur_per_1m_inputandeur_per_1m_output
(EUR per one million tokens, six decimal places kept, the configured spelling kept),valid_from(today when
left out; a past day re-prices the usage since then, a future day schedules the change),note(owned: left
out, it is cleared), throughPUT /ai/rate-card/{tier}. The same rate again changes nothing on the platform, so
a second apply sends nothing and an apply after a portal change puts the rate back;valid_toreads when a
change is scheduled after it. Destroy forgets only (the platform never removes a list rate); import by tier.ataila_ai_rate_planresource: a tenant's whole rate plan,rates= map of tier to
{eur_per_1m_input, eur_per_1m_output, note}, optionalvalid_from(sent with each change, not read back),
throughPUT /tenants/{id}/ai-rate-plan. A tier left out goes back to the list rate on the next apply, and the
plan warns, naming it;effective(what each tier costs the tenant today, its basis and the list rate beside it)
andcontract_includedread back. Destroy ends the plan (DELETE, not gated: a price change, nothing removed);
import by tenant id;tenant_idforces a new resource.ataila_ai_rate_cardandataila_ai_rate_plandata sources: the whole card (per tiercurrent,upcoming,
seedable; the history) and one tenant's plan (rates,upcoming,effective,contract, the history).ataila_ai_usagedata source (tenant_id, optionalmonth,YYYY-MM, default the current month): one tenant's
month of AI gateway usage, rated —totals,by_key(withrowsper tier and model and each key's
attribution),by_tier(with the rate),by_day,forecast,budget(theai_budget_eur_monthquota against
the spend),rated_eur,rate_basis,rate_bases,unrated_tiers,rated_complete; the gateway's own shadow
price asshadow_usd.ataila_ai_gateway_usage(optionalmonth): every tenant's month, rated, and the
unattributed keys.
Minimum platform, per feature
- The provider still works with every platform from release 1.0.187 on. Tenant quotas, the catalogue and the
order reads need platform release 1.0.233 or later (client.ReleaseQuotasOrders); AI usage, the rate card and
rate plans need 1.0.237 or later (client.ReleaseAIBilling). A configuration that uses one of them on an older
platform is refused at plan time, before any request, naming both releases.
Contract
api/openapi-v1.jsonis the platform's contract with release 1.0.237's operations (98). Since 1.0.206 it adds
the five quota, catalogue and order operations (tenant_quotas_get,tenant_quotas_put,catalogue_items_list,
tenant_orders_list,orders_get; platform 1.0.233) and the seven AI usage and rate operations
(tenant_ai_usage_get,ai_gateway_usage_get,ai_rate_card_get,ai_rate_card_put,tenant_ai_rate_plan_get,
tenant_ai_rate_plan_put,tenant_ai_rate_plan_delete; 1.0.237) with their schemas, and from the releases in
betweenapp_subdomainon projects, thehostname_takenrefusal and documented codes; nothing is removed or
changed (the platform's additive guard checks every release against the contract published with 1.0.0).
Documentation
- Pages and examples for the three new resources and the eight new data sources, and
examples/sp-tenant/: a
service provider's customer tenant from code — its quota set, an AI gateway key inside it, its own AI rates, and
its orders and month's rated usage read back; its README shows how to run it with a provider built from a
checkout (a development override) before a release is published. - The README shows the company's logo at the top (
docs/images/ataila-logo.png). - The documentation link points to the company's website, https://www.ataila.com/developers/terraform, in the
README and on the registry's overview page. - "Switching between OpenTofu and Terraform" (README and the registry's overview page) follows what provider
1.1.0 did with OpenTofu 1.12.3 and Terraform 1.9.8 on 2026-10-03. Terraform → OpenTofu is not "nothing":
tofu planandtofu outputwork on a Terraform state, buttofu showfails with Failed to load plugin
schemas … unavailable provider "registry.terraform.io/ataila/ataila" until
tofu state replace-provider registry.terraform.io/ataila/ataila registry.opentofu.org/ataila/ataila(or one
tofu apply) has run. OpenTofu → Terraform: the error a user meets first isterraform init's Failed to
query available provider packages … registry.opentofu.org does not have a provider named
registry.opentofu.org/ataila/ataila, quoted now, and the order isterraform state replace-provider, then
terraform init(again, if it ran before). - New, temporary: "OpenTofu until its registry lists the provider". While the OpenTofu registry listing is
pending (opentofu/registryPR #5669; the signing key, PR #5671, was merged on 2026-10-02), OpenTofu installs
the provider from a filesystem mirror filled from the GitHub release (the platform archive or the air-gapped
mirror bundle).tofu initreports it asunauthenticated; the section gives the three commands that check
the archive against the signedSHA256SUMSinstead.
CI
- The acceptance tests of the quota, catalogue and order objects are in the
tenancydomain
(scripts/ci/acc-domains.sh:CatalogueandOrderadded); those of AI usage and rates
(TestAccAI…) inai-licence-brand. - The leak guard allows
www.ataila.com, the company's website. The names under the company's earlier website
domain stay allowed for the released history only; no file names that domain any more.
v1.1.0
A minor release: additions only, under the stability promise of 1.0.0. A configuration and a state of 1.0.0
plan with no changes.
Added
k8s_quotaonataila_project(resource and data source): a Kubernetes project's namespace quota per
environment (dev,uat,prod), GPU scheduling included — the eleven quota keys as Kubernetes quantities
(req_cpu…pods,gpu_exclusivethe guaranteed floor in whole cards,gpu_borrow,gpu_shared,
fair_weight) plus what the platform reports (namespace,cluster,tier,gpu_queue,gpu_enabled,
overridden,overridden_keys). The resource sends the keys a configuration sets, withreason, through
PATCH /projects/{id}/k8s-quota/{env}after the project's own change, one request per environment; a key
left out keeps its current value, a count spelled with leading zeros keeps the configuration's spelling, a
changed reason alone re-sends the environment's overridden keys unchanged with it. A refusal (quota_refused,
quota_conflict, 403 withoutk8s-gpu-admin-global) fails the apply with the platform's reason, and the
state records what did change (the project's settings, the environments before the refused one), so the next
plan shows only what is left — also when reading the project back afterwards fails (the state is then built
from the platform's answers to the requests that went through); on create the project is created and
tainted, and the error says how to keep it. Settingk8s_quotaon a VM-backend project fails validation.
Removingk8s_quotafrom the configuration, or destroying the project, changes no quota.app_gatewayonataila_projectmay readataila, the value the platform's own project reports (platform
1.0.206 and later); it cannot be set.
Minimum platform, per feature
- The provider still works with every platform from release 1.0.187 on. A feature that came later is refused
only where it is used:k8s_quotaneeds platform release 1.0.203 or later, and a configuration that sets it
on an older platform is refused at plan time, on create and on update, before any request, naming both
releases. On such a platform the attribute reads null, in the resource and in the data source.
Contract
api/openapi-v1.jsonis the platform's export of release 1.0.206, unchanged. Since 1.0.187 it adds
Project.k8s_quota,KubernetesQuota,KubernetesQuotaPatch,KubernetesQuotaUpdatedand the two quota
operations (PATCHandDELETE /projects/{project_id}/k8s-quota/{env}, platform 1.0.203), and the read-only
app_gatewayvalueataila(1.0.206); everything else is unchanged.
CI
- Lint fails when a copyright notice names another holder than ATAILA Kft.
- The strict leak guard (
leak-guard:strict,scripts/leak-guard.sh --strict) also fails when a commit in the
scanned history has an author or committer address other than the company's, when aCo-Authored-Bytrailer
names another address than the AI assistant's no-reply address, or when an annotated tag in that history has
another tagger (README, "Leak guard": the public history carries the organisation's identity only). A normal
run reports such an address and passes. Every mirror job needs the strict guard, so such a commit no longer
reaches the public repository. Tested on scratch repositories in theleak-guardjob. - The two commits of the
k8s_quotawork, made after 1.0.0 with another author address, were re-authored to the
company address before this release (trees, messages and dates unchanged but for oneCo-Authored-By
trailer, which now names the model as the others do). A temporary job forced the rewritten default branch onto
the public repository once and was removed again;v1.0.0and everything before it are unchanged.
v1.0.0
The first public release of the OpenTofu and Terraform provider for the ATAILA Cloud Platform, published to both
registries as ataila/ataila.
Stability promise
From this release on, the provider follows semantic versioning. Within 1.x no resource, data source or
attribute is removed or renamed, no attribute changes its type or meaning, and no change needs a configuration
or a state to change: such a change waits for 2.0.0 and is announced in this file first. A minor release adds
(resources, data sources, attributes, accepted values); a patch release fixes. The platform's API v1, which the
provider speaks, changes only by addition. ~> 1.0 takes every 1.x release.
Contract
- The platform's
/api/v1of platform release 1.0.187 (API 1.0.0), vendored as the platform exports it
(api/openapi-v1.json). The provider needs platform release 1.0.187 or later (API 1.0.0 or later within
major version 1) and refuses an older platform when it is configured, naming the minimum: every platform
since 1.0.155 serves API 1.0.0, but before 1.0.176 the members had other names, and before 1.0.187 the
Idempotency-Keyparameter and theLocationheader were not declared.
Provider objects
- 17 resources:
ataila_customer,ataila_tenant,ataila_tenant_membership,ataila_user,
ataila_user_role_grant,ataila_ai_gateway_key,ataila_ai_serving_tier,ataila_project,
ataila_project_provisioning,ataila_project_member,ataila_project_prod_lock,
ataila_release_promotion,ataila_ai_model,ataila_ai_model_node_cache,ataila_licence_bundle,
ataila_brandandataila_brand_asset. - 27 data sources:
ataila_meta,ataila_whoami,ataila_customer,ataila_tenant,ataila_tenants,
ataila_user,ataila_users,ataila_permission_catalog,ataila_ai_gateway,ataila_ai_serving_tiers,
ataila_project,ataila_projects,ataila_project_stages,ataila_release_state,
ataila_release_operation,ataila_ai_model,ataila_ai_models,ataila_ai_model_storage,
ataila_ai_model_launch_catalog,ataila_ai_load_targets,ataila_ai_node,ataila_ai_nodes,
ataila_dgx_clusters,ataila_licence,ataila_licence_socket_facts,ataila_brandand
ataila_brand_asset. - Both CLIs are first-class: OpenTofu and Terraform 1.6 and later, every change tested against the oldest and
the newest of each, with one state shared by both.
Upgrading
- From 0.8.x: nothing changes in a configuration or a state;
planshows no changes. Move the version
constraint to~> 1.0. - From 0.7.x: the same, plus 0.8.0's changes (nested lists and objects became described nested attributes,
values and types unchanged). - From 0.6.x or older: 0.7.0 renamed every attribute that named an internal system (its section below lists each,
old and new). The state upgrades itself on the first read; the configuration must use the new names.
Distribution
- Signed with the organisation's RSA-4096 key, whose public half is
docs/signing-key.asc. - The GitHub release holds the archives,
SHA256SUMS, its signature and the registry manifest, and as extra
assets the air-gapped mirror bundle (terraform-provider-ataila_1.0.0_mirror.zip) and its.sha256. - Problems and questions: support@ataila.com; documentation at https://www.ataila.eu/developers/terraform. The
public repository's issue tracker is off.
Added since 0.8.0
ataila_project_provisioning:running_stages,failed_stages,needs_action_stagesandmessage.ataila_branddata source:attributionandfirst_party(read-only on the platform).- The customer resource and data source state that the GitLab group's live status is not read.
- The provider refuses a platform older than release 1.0.187 when it is configured (see Contract).
- Proven end to end on a real platform (release 1.0.196) under both CLIs: read, import, create, no diff,
drift, frozen keys, the destroy switches, a project with its provisioning, a person, and the audit log.
CI
- The release job no longer
go installs goreleaser: that fetched hundreds of megabytes of goreleaser's own
modules and filled a shared runner's disk in the v0.8.0 release. It downloads goreleaser's release binary
for linux/amd64 at a pinned version, checked against a pinned SHA-256 like the CLIs
(scripts/ci/toolchain.sh,ensure_goreleaser), into the job's.tmp, which is removed after the job. The
job keeps building with the Go cache lint saves, and saves none. release:dry-runon the default branch exercises that path without a tag: the download,goreleaser check, and a snapshot build for the runner's platform.- The Go cache no longer stays in the runners' builds slots: every job but lint removes it after its script,
and lint, the one job that saves it, drops the build cache first (so the saved cache holds the modules and
the toolchain). Each job's log ends with the size its slot is left at. - Leak guard: the private key pattern also catches the armour of an OpenPGP private key (
BEGIN PGP PRIVATE KEY BLOCKbetween the dashes); it caught the OpenSSH, RSA, EC, DSA, encrypted and plain PKCS#8 headers
already. Its self-test checks every armour, andscripts/ci/test-leak-guard.sh, run by the leak-guard job,
plants each in a scratch repository (in the tree and in history) and checks that a public key block, as
docs/signing-key.ascholds, is no finding. mirror:githubnever pushes a 0.x tag andpublish:githubrefuses any version below 1.0.0, in their rules
and in the scripts;scripts/ci/test-mirror-github.sh(run by lint) checks the mirror against a fake public
repository, and the publisher's unit tests refuse fake 0.x tags.publish:githubattaches the air-gapped mirror bundle and its.sha256to the release, after checking the
bundle against its sum.- The leak guard also refuses GitHub token shapes (classic and fine-grained); their findings are never printed.
mirror:githubmirrors the default branch only; a release tag is mirrored bymirror:github:tag, which runs
only afterreleasesucceeded, so that no tag reaches the public repository without its release.leak-guard:strictfails if one of the parent group's inherited CI/CD variables holds a value in this
project's pipelines (they are shadowed by empty project-level variables).- The history was rewritten once before publication so that every commit's author and committer, and every
tag's tagger, is the company address; the trees, messages and dates are unchanged, and v0.4.0 to v0.8.0
were re-created on the rewritten commits. A temporary job forced the rewritten default branch onto the
public repository once and was removed again.