The A.R.C. template system generates Docker Compose configurations from embedded templates.
Templates are Go text/template files that render service configurations. The system provides:
- Embedded templates compiled into the binary
- Template caching for performance
- Custom functions for common operations
- Variable substitution for customization
- Validation at startup
pkg/catalog/templates/
├── docker-compose/ # Service docker-compose snippets
│ ├── generic.yml.tmpl # Fallback template
│ ├── oracle.yml.tmpl # PostgreSQL
│ ├── sonic.yml.tmpl # Redis
│ └── ...
├── configs/ # Service configuration files
│ ├── postgres/
│ │ └── postgresql.conf.tmpl
│ ├── redis/
│ │ └── redis.conf.tmpl
│ └── ...
└── shared/ # Shared partials
├── networks.yml.tmpl
└── volumes.yml.tmpl
Templates use Go's text/template syntax:
# Comments
{{ .Service.Codename }}:
image: {{ .Service.Image }}
# Conditionals
{{- if .Vars.enabled }}
enabled: true
{{- end }}
# Loops
{{- range .Service.Ports }}
- "{{ .Host }}:{{ .Container }}"
{{- end }}
# With blocks
{{- with .Service.Environment }}
environment:
{{- range . }}
- {{ .Name }}={{ .Default }}
{{- end }}
{{- end }}Use - to trim whitespace:
{{-trims leading whitespace-}}trims trailing whitespace
| Field | Type | Description |
|---|---|---|
.Service.Codename |
string | Unique service name |
.Service.Technology |
string | Technology name |
.Service.Role |
ServiceRole | Service category |
.Service.Description |
string | Human description |
.Service.Version |
string | Version string |
.Service.Image |
string | Docker image |
.Service.Ports |
[]PortMapping | Port mappings |
.Service.Dependencies |
[]string | Dependency codenames |
.Service.Environment |
[]EnvVar | Environment variables |
.Service.Volumes |
[]VolumeMount | Volume mounts |
.Service.ConfigFiles |
[]string | Config file names |
.Service.Aliases |
[]string | Alternative names |
| Field | Type | Description |
|---|---|---|
.Host |
int | Host port |
.Container |
int | Container port |
.Protocol |
string | tcp or udp |
.Description |
string | Port description |
| Field | Type | Description |
|---|---|---|
.Workspace.Name |
string | Workspace name |
.Workspace.DataDir |
string | Data directory |
.Workspace.ConfigDir |
string | Config directory |
.Workspace.Network |
string | Network name |
User-provided variables via .Vars:
# Access with defaults
{{ default "default_value" .Vars.my_variable }}
# Check existence
{{- if .Vars.optional_feature }}
feature_enabled: true
{{- end }}# Quote a string
{{ quote .Vars.name }} # "value"
# Case conversion
{{ lower .Service.Codename }} # heimdall
{{ upper .Service.Role }} # INFRASTRUCTURE
# String operations
{{ replace "_" "-" .Name }} # foo-bar
{{ contains "test" .Value }} # true/false
{{ hasPrefix "arc-" .ContainerName }} # true/false
{{ hasSuffix ".yml" .FileName }} # true/false# Reference with optional default
{{ env "DATABASE_URL" }} # ${DATABASE_URL}
{{ env "LOG_LEVEL" "info" }} # ${LOG_LEVEL:-info}# OS detection
{{ if isDarwin }}
# macOS specific
{{ end }}
{{ if isLinux }}
# Linux specific
{{ end }}
{{ platform }} # darwin, linux, windows# Default values
{{ default "fallback" .Vars.value }}
# YAML serialization
{{ toYAML .Config }}
# Indentation
{{ indent 4 .MultiLineContent }}# Join strings
{{ join "," .Service.Aliases }} # alias1,alias2
# Split string
{{ range split "," .CSVValue }}
- {{ . }}
{{ end }}{{ .Service.Codename }}:
image: {{ .Service.Image }}
container_name: arc-{{ .Service.Codename }}
restart: unless-stopped
{{- if .Service.Ports }}
ports:
{{- range .Service.Ports }}
- "{{ .Host }}:{{ .Container }}/{{ .Protocol }}"
{{- end }}
{{- end }}
networks:
- {{ .Workspace.Network }}{{ .Service.Codename }}:
image: {{ .Service.Image }}
{{- if .Service.Dependencies }}
depends_on:
{{- range .Service.Dependencies }}
{{ . }}:
condition: service_healthy
{{- end }}
{{- end }}{{ .Service.Codename }}:
environment:
{{- range .Service.Environment }}
{{- if .Required }}
- {{ .Name }}=${{ printf "{%s}" .Name }}
{{- else if .Default }}
- {{ .Name }}={{ .Default }}
{{- end }}
{{- end }}{{ .Service.Codename }}:
{{- if .Vars.enable_debug }}
command: ["--debug"]
{{- end }}
{{- if .Vars.resources }}
deploy:
resources:
limits:
memory: {{ default "512M" .Vars.memory_limit }}
{{- end }}{{ .Service.Codename }}:
volumes:
{{- if isDarwin }}
# macOS uses delegated for performance
- {{ .Workspace.DataDir }}/data:/data:delegated
{{- else }}
- {{ .Workspace.DataDir }}/data:/data
{{- end }}renderer := catalog.NewTemplateRenderer()
err := renderer.ValidateTemplate("test", templateContent)
if err != nil {
// Template has syntax error
}catalog, _ := catalog.NewEmbeddedCatalog()
vars := catalog.NewTemplateVars()
vars.Set("workspace_name", "my-workspace")
output, err := catalog.RenderServiceTemplate("oracle", vars)# Validate all embedded templates
go test ./pkg/catalog/... -run TestValidateAllTemplates
# Update golden files after changes
go test ./pkg/catalog/... -update-golden- Use defaults: Always provide sensible defaults for optional variables
- Trim whitespace: Use
{{-and-}}to control output formatting - Document variables: Comment what each variable controls
- Test edge cases: Test with empty/missing variables
- Follow YAML spec: Ensure output is valid YAML
- Include health checks: Every service should have a healthcheck