d9d8cc7b6df4c6c9c774f4968ef9e9dc118fd9da
The API returns null for empty arrays, but OpenTofu requires that the state match the plan exactly — an empty list [] in the plan must remain [] in the state, not become null. This caused "inconsistent result after apply" errors on every resource with empty optional list fields like mutable_patterns and ban_tags.
terraform-provider-artifactapi
Terraform provider for managing ArtifactAPI remotes and virtual repositories.
Requirements
- Go >= 1.23
- Terraform >= 1.0
Building
make build
Installation
Install the provider to your local Terraform plugin directory:
make install
This places the binary at ~/.terraform.d/plugins/git.unkin.net/unkin/artifactapi/<version>/<os_arch>/.
Provider Configuration
terraform {
required_providers {
artifactapi = {
source = "git.unkin.net/unkin/artifactapi"
version = "0.0.1"
}
}
}
provider "artifactapi" {
endpoint = "https://artifactapi.example.com"
}
| Attribute | Required | Description |
|---|---|---|
endpoint |
Yes | ArtifactAPI server endpoint URL |
Resources
Remote Resources
Per-type remote resources manage upstream repository proxies. Each type applies its own mutability classification rules automatically (e.g., Docker classifies tag manifests as mutable and blobs as immutable; Helm classifies index.yaml as mutable).
Available resource types:
artifactapi_remote_genericartifactapi_remote_dockerartifactapi_remote_helmartifactapi_remote_pypiartifactapi_remote_npmartifactapi_remote_rpmartifactapi_remote_alpineartifactapi_remote_puppetartifactapi_remote_terraformartifactapi_remote_goproxy
Common Attributes
| Attribute | Required | Default | Description |
|---|---|---|---|
name |
Yes | Unique name (forces replacement on change) | |
base_url |
Yes | Upstream repository URL | |
description |
No | "" |
Human-readable description |
username |
No | "" |
Upstream auth username (sensitive) |
password |
No | "" |
Upstream auth password (sensitive) |
immutable_ttl |
No | 0 |
TTL in seconds for immutable artifacts (0 = cache forever) |
mutable_ttl |
No | 3600 |
TTL in seconds for mutable artifacts |
check_mutable |
No | true |
Enable conditional revalidation for mutable artifacts |
patterns |
No | Allowlist of path patterns to proxy (empty = all) | |
blocklist |
No | Paths to always deny (checked before patterns) | |
mutable_patterns |
No | Override: treat matching paths as mutable | |
immutable_patterns |
No | Override: treat matching paths as immutable | |
quarantine_enabled |
No | false |
Enable quarantine for new artifacts |
quarantine_days |
No | 3 |
Days to quarantine new artifacts |
stale_on_error |
No | true |
Serve stale cache when upstream is unreachable |
Docker-specific Attributes
| Attribute | Default | Description |
|---|---|---|
ban_tags_enabled |
false |
Enable tag banning |
ban_tags |
List of tags to ban |
Terraform-specific Attributes
| Attribute | Default | Description |
|---|---|---|
releases_remote |
"" |
Name of a generic remote for download URL rewriting |
Example
resource "artifactapi_remote_docker" "dockerhub" {
name = "dockerhub"
base_url = "https://registry-1.docker.io"
immutable_ttl = 0
mutable_ttl = 300
ban_tags_enabled = true
ban_tags = ["latest"]
patterns = [
"^library/postgres",
"^library/redis",
]
}
Virtual Resources
Virtual repositories merge multiple remotes of the same package type into a single endpoint.
resource "artifactapi_virtual" "helm" {
name = "helm"
package_type = "helm"
description = "All helm repos merged"
members = [
artifactapi_remote_helm.jetstack.name,
artifactapi_remote_helm.hashicorp_helm.name,
]
}
| Attribute | Required | Description |
|---|---|---|
name |
Yes | Unique name (forces replacement on change) |
package_type |
Yes | Package type of member remotes |
description |
No | Human-readable description |
members |
Yes | List of remote names to include |
Data Sources
artifactapi_remote
Read an existing remote's configuration.
data "artifactapi_remote" "dockerhub" {
name = "dockerhub"
}
artifactapi_virtual
Read an existing virtual repository's configuration.
data "artifactapi_virtual" "helm" {
name = "helm"
}
Import
Resources can be imported by name:
terraform import artifactapi_remote_docker.dockerhub dockerhub
terraform import artifactapi_virtual.helm helm
Development
make build # Build the provider binary
make install # Install to local plugin directory
make test # Run tests
make lint # Run go vet
make fmt # Format code
make clean # Remove binary
Description
Languages
Go
98%
Makefile
2%