Configuration
Config is provided with a YAML file:
prefix: string
sources:
- url: https://github.com/entigolabs/entigo-infralib-release | path
version: stable | semver | branch
include: []string
exclude: []string
force_version: bool
username: string
password: string
repo_path: string
ca_file: string
use_oci_digests: bool
verify_signature: bool
destinations:
- name: string
git:
url: string
key: string
key_password: string
username: string
password: string
author_name: string
author_email: string
insecure: bool
ca_file: string
notifications:
- name: string
context: string
message_types: []string
slack:
token: string
channel_id: string
teams:
webhook_url: string
api:
url: string
wrapper_url: string
headers: map[string]string
oauth:
client_id: string
client_secret: string
token_url: string
scopes: []string
schedule:
update_cron: string
agent_version: latest | semver
base_image_source: string
base_image_version: stable | semver
enable_opentofu: deprecated - bool
use_oci_proxy: bool
provider:
inputs: map[string]string
aws:
default_tags:
tags: map[string]string
endpoints: map[string]string
ignore_tags:
key_prefixes: []string
keys: []string
kubernetes:
ignore_annotations: []string
ignore_labels: []string
steps:
- name: string
type: terraform | argocd-apps
approve: deprecated - minor | major | never | always | force | reject
manual_approve_run: always | changes | removes | never | reject
manual_approve_update: always | changes | removes | never | reject
base_image_source: string
base_image_version: stable | semver
vpc:
attach: bool
id: string
subnet_ids: multiline string
security_group_ids: multiline string
kubernetes_cluster_name: string
argocd_namespace: string
modules:
- name: string
source: string
version: stable | semver
http_username: string
http_password: string
default_module: bool
inputs: map[string]interface{}
provider:
inputs: map[string]string
aws:
default_tags:
tags: map[string]string
endpoints: map[string]string
ignore_tags:
key_prefixes: []string
keys: []string
kubernetes:
ignore_annotations: []string
ignore_labels: []string
Complex values need to be as multiline strings with | symbol.
Source version is overwritten by module version. Default version is stable which means latest release of the source repository.
- prefix - prefix used for AWS/GCloud/Oracle resources, bucket folders/files and OpenTofu resources, limit 10 characters, overwritten by the prefix flag/env var
- sources - list of source repositories for Entigo Infralib modules
- url - url of the source repository or path to the local directory. Path must start with
./or../Path will set force_version to true and uselocalas the version. Path only works with the local pipeline execution type. - version - highest version of Entigo Infralib modules to use
- include - list of module sources to exclusively include from the source repository
- exclude - list of module sources to exclude from the source repository
- force_version - sets the specified version to all modules that use this source, useful for specifying a branch or tag instead of semver or digest for OCI, default false. Modules with forced version always allow running in parallel during executions. Warning! Before changing from true to false, force a version that follows semver.
- username - username for git authentication
- password - password for git authentication, it's recommended to use custom replacement tags, e.g.
"{{ .output-custom.git-password}}" - repo_path - path to the git repository root directory, default uses Go's TempDir to create a directory named after the repository url. Use debug logging to see the path. Warning! Agent prunes the repo to match the remote.
- ca_file - name of the CA certificate file in the
./ca-certificatesfolder to use for git authentication - use_oci_digests - use OCI digests for module sources instead of version tags when using OCI source with version tag, default false
- verify_signature - verify the OCI index signature when using OCI entigolabs source, true value forces use_oci_digests to true as well, default false
- url - url of the source repository or path to the local directory. Path must start with
- destinations - list of destinations where the agent will push the generated step files, in addition to the default bucket
- name - name of the destination
- git - git repository must be accessible by the agent. For authentication, use either key or username/password. For the key and password, it's recommended to use custom replacement tags, e.g.
"{{ .output-custom.git-key }}"- url - url of the git repository
- key - PEM encoded private key for authentication
- key_password - optional, password for the private key
- insecure_host_key - accept any host key when using private key, default false
- username - username for authentication
- password - password for authentication
- author_name - author name for commits, default Entigo Infralib Agent
- author_email - author email for commits, default no-reply@localhost
- insecure - allow insecure connection, default false
- ca_file - name of the CA certificate file in the
./ca-certificatesfolder to use for git authentication
- notifications - send notifications with selected types, each notifier can only use one subtype
- name - name of the notifier
- context - optional, extra context added to the notification
- message_types - list of types of messages to send, possible values
started | approvals | sources | progress | schedule | success | failure, default[approvals, failure]. More info in Message types - api - send notifications to a custom API
- url - url for the api
- wrapper_url - optional, enables gRPC connection while provisioning for sending logs and plan summaries. Full URL of the backend endpoint (
https://host[:port][/path]). The path segment is preserved and prepended to gRPC method names. When omitted, provision runs the entrypoint transparently. When set, the config is stored in Secret Manager and injected into each pipeline execution as theWRAPPER_CONFIGenv var. - headers - key-value pair of headers to add to the request
- oauth - optional oauth2 configuration for the api
- slack - send notifications to slack
- token - slack access token, it's recommended to use custom replacement tags, e.g.
"{{ .output-custom.slack-token }}" - channel_id - slack channel id
- token - slack access token, it's recommended to use custom replacement tags, e.g.
- teams - send notifications to teams
- webhook_url - webhook url for the teams channel, possible options include Teams Workflow or Power Automate, more info in go-teams-notify GitHub
- schedule - allows scheduling CodePipeline/Cloud Run Job executions. More info in Scheduling
- update_cron - cron expression in UTC for scheduling agent update executions.
- agent_version - image version of Entigo Infralib Agent to use
- base_image_source - source of Entigo Infralib Base Image to use
- base_image_version - image version of Entigo Infralib Base Image to use, default uses the version from step
- enable_opentofu - deprecated, make Infralib use OpenTofu instead of Terraform, default true.
- use_oci_proxy - replace OCI source url host with proxy if registry proxy module has been applied, excluding modules that are part of the same step as the proxy module, default false
- provider - provider values to add for all OpenTofu steps
- inputs - variables for provider tf file
- aws - aws provider default, ignore tags and endpoints to add
- kubernetes - kubernetes provider ignore annotations and labels to add
- steps - list of steps to execute
- name - name of the step
- type - type of the step
terraform | argocd-apps - approve - deprecated, approval type for the step, possible values
minor | major | never | always | force | reject, default always. More info in Auto approval logic - manual_approve_update - approval type for the step when using the update command, possible values
always | changes | removes | never | reject, default removes. More info in Auto approval logic - manual_approve_run - approval type for the step when using the run command, possible values
always | changes | removes | never | reject, default changes. More info in Auto approval logic - base_image_source - source of Entigo Infralib Base Image to use
- base_image_version - image version of Entigo Infralib Base Image to use, default uses the newest module version
- vpc - vpc values to add
- attach - attach vpc to code build/cloud run job, if other fields are empty then uses default vpc based on typed output of a vpc module, default nil. When nil, the value will be set based on the step type, for
argocd-appssteps the value will be set totrue - id - vpc id for code build/cloud run job, gcloud default
{{ .toutput.vpc.vpc_name }}, aws default{{ .toutput.vpc.vpc_id }} - subnet_ids - vpc subnet ids for code build/cloud run job/container instance, gcloud default
[{{ .toutput.vpc.private_subnets[0] }}], aws default[{{ .toptout.vpc.control_subnets | .toutput.vpc.private_subnets }}], oracle no default (a step that attaches its own vpc must set this, otherwise the container runs in the agent's bootstrap subnet) - security_group_ids - vpc security group ids for code build/cloud run job, gcloud no default, aws default
[{{ .toutput.vpc.pipeline_security_group }}]
- attach - attach vpc to code build/cloud run job, if other fields are empty then uses default vpc based on typed output of a vpc module, default nil. When nil, the value will be set based on the step type, for
- kubernetes_cluster_name - kubernetes cluster name for argocd-apps steps, gcloud default
{{ .toutput.gke.cluster_name }}, aws default{{ .toutput.eks.cluster_name }} - argocd_namespace - kubernetes namespace for argocd-apps steps, default argocd
- modules - list of modules to apply
- name - name of the module
- source - source of the OpenTofu module, can be an external git repository beginning with git:: or git@
- version - highest version of the module to use
- http_username - username for external repository authentication
- http_password - password for external repository authentication
- default_module - when using
tmodulereplacement, default module will be used if multiple modules of the same type exist, default false - inputs - optional, map of inputs for the module, string values need to be quoted. If missing, inputs are optionally read from a yaml file that must be located in the
./config/<stepName>directory with a name<moduleName>.yaml
- provider - provider values to add
- inputs - variables for provider tf file
- aws - aws provider default, ignore tags and endpoints to add
- kubernetes - kubernetes provider ignore annotations and labels to add
Including and excluding modules in sources
Agent associates modules with sources for requesting module files. Module association is done by checking if a source includes a module. This is done by checking the source list from top to bottom. Source includes a module if:
- source config
includeproperty contains the module source - source config
excludeproperty does not contain the module source - module source path is a subdirectory in source
modulesfolder
For modules in steps with type argocd-apps, agent currently prefixes the k8s part of the path in the module source automatically.
Example
sources:
- url: https://github.com/entigolabs/entigo-infralib-release
exclude: ["argocd"]
include:
- aws/eks
- url: https://github.com/entigolabs/entigo-infralib
Auto approval logic
Each step can be configured how it automatically approves infrastructure changes for the agent's run and update commands. To decide when to auto approve changes. If the planning stage of a step finds no changes, then the pipeline apply stage will be skipped. If only one of the manual_approve_* properties is set for a step, then the other property uses the default value. Possible values for the manual_approve_run and manual_approve_update are:
always- will ask for user manual approval when resources are added, changed or removed.changes- will ask for user manual approval when resources are changed or removed. (default formanual_approve_run).removes- will ask for user manual approval when resources are removed (default formanual_approve_update).never- will never ask for manual approval. (DANGEROUS!)reject- stop the pipeline instead of approving, marks the step as failed. This can be used to generate plan files without applying them.
Step property approve has been deprecated and replaced by manual_approve_run and manual_approve_update. If none of those fields is set then approve will be used with default always value for backwards compatibility.
When using the approve property, auto approve type is only considered when resources will be changed. Adding resources doesn't require manual approval. Destroying resources always requires manual approval, except when using type force. Approve always means that manual approval is required, never means that agent approves automatically. Types major and minor require manual approval only when any of the step modules has a major or minor semver version change. Modules with external source require manual approval.
Overriding config values
Step, module and input field values can be overwritten by using replacement tags {{ .type.key }}. Possible replacement tags are:
| Type | Key / Format | Example | Description |
|---|---|---|---|
agent | version.stepName.moduleName | .agent.version.infra.eks | Configured version of the specified module. |
| accountId | .agent.accountId | Configured AWS account ID. | |
| organizationId | .agent.organizationId | AWS organization ID, Google Cloud organization ID or Oracle tenancy OCID. Empty if not in an organization. | |
| region | .agent.region | Configured cloud provider region. | |
| vaultId | .agent.vaultId | Managed Oracle Vault OCID, only supported for Oracle provider. | |
| providerDomain | .agent.providerDomain | Cloud provider domain of the region, e.g. amazonaws.com, googleapis.com or oraclecloud.com. | |
config | fieldName | .config.prefix | Value from the provided config field. Config replacement does not support indexed paths. |
module | name | .module.name | Name of the module itself (for module inputs and input files only). |
| source | .module.source | Source of the module itself (for module inputs and input files only). | |
optout | stepName.moduleName.key | .optout.infra.eks.cluster_arn | Optional value from OpenTofu output from specific step/module. Defaults to empty string. |
output | stepName.moduleName.key | .output.infra.eks.cluster_arn | Value from OpenTofu output from specific step/module. |
output-custom | key | .output-custom.param-key | Value from AWS SSM parameter, GCloud SM or OCI Vault. |
step | name | .step.name | Name of the step containing the module. |
tinput | type.Key | .tinput.argocd.argocd.global.domain | Value from a module inputs in the current step. Falls back to values files for argocd-apps steps |
tmodule | type | .tmodule.eks | Name of the module with a specified type. |
toptmodule | type | .toptmodule.eks | Optional name of the module with a specified type. |
toptout | type.key | .toptout.eks.cluster_arn | Optional value from OpenTofu output based on module type. Defaults to empty string. |
toptin | type.key | .toptin.argocd.argocd.global.domain | Optional value from a module inputs in the current step, fallback same as tinput. Defaults to empty string. |
toutput | type.key | .toutput.eks.cluster_arn | Value from OpenTofu output based on module type. |
tsmodule | type | .tsmodule.eks | Name of the typed module in the current step. |
For output types, if the value is not found from OpenTofu output, then the value is requested from AWS SSM Parameter Store, Google Cloud Secret Manager, or OCI Vault.
For example, {{ .output.stepName.moduleName.key-1 }} will be overwritten with the value from OpenTofu output moduleName__key-1. As a fallback, uses SSM Parameter Store parameter /entigo-infralib/config.prefix-stepName-moduleName-parentStep/key-1.
It's possible to build a custom array by using yaml multiline string, even mixing replaced values with inputted values. For example creating a list of strings for OpenTofu:
inputs:
key-1: |
["{{ .output.stepName.moduleName.key-1 }}", "value-1", "value-2"]
List indexes
If the parameter type is StringList then it's possible to use an index to get a specific value, e.g. {{ .output.stepName.moduleName.key-1[0] }} or a slice by using a range, e.g. [0-1]. In case of OpenTofu output, it's also possible to use a map key as the index, e.g. {{ .output.stepName.moduleName.key-1[key-2] }}.
Escaping replacement tags
Replacement tags support escaping with inner {{`{{ }}`}} tags. For example, {{`{{ .dbupdate }}`}} will be replaced with {{ .dbupdate }}. This can be used to pass helm template values through the agent.
Optional replacement tags
If the output value is optional then use optout or toptout, it will replace the value with an empty string if the module or output is not found. This also applies to toptin. Optional tag can be combined with the | operation to add (multiple) fallback values. Quotation marks can be used to provide a default value. For example {{ .optout.stepName.ModuleName.key-1 | "default" }}.
Required replacement tags
A chain of optional values can be marked as required as a whole by ending it with required. If every value in the chain resolves to an empty string then the agent fails with an error naming the whole tag, instead of replacing the tag with an empty string. This allows every value in the chain to be optional, which makes cross cloud chains both safe and order independent.
inputs:
name: '{{ .toptin.aws-alb.global.internalGateway | .toptin.google-gateway-global.internalGateway | required }}'
host: '{{ .toptout.route53.int_domain | .toptout.dns.int_domain | required }}'
required is a reserved word, it never provides a value itself. It must be the last value in the chain and must be preceded by at least one value. It can't be combined with a default value or with an agent value, both of which always resolve.
Including files in steps
It's possible to include files in steps by adding the files into a ./config/<stepName>/include subdirectory. File names can't include main.tf, provider.tf or backend.conf as they are reserved for the agent. For ArgoCD, reserved name is argocd.yaml and named files for every module module-name.yaml. Files will be copied into the step directory which is used by OpenTofu and ArgoCD as step context.
Including CA certificates
It's possible to include CA certificates by adding the files into a ./ca-certificates subdirectory. Files will be copied into the bucket root and each step directory for Infralib.
Notifications
The agent emits lifecycle events at three nested levels of granularity so external systems can observe progress and outcomes:
- Agent execution — the entire agent invocation. Emits a start event and a terminal success or failure event.
- Pipeline — each release iteration applied by the agent. A
runcommand applies a single release (one pipeline). Anupdatecommand can apply multiple releases sequentially, each emitting its own start, success, or failure events. - Step — each configuration step within a pipeline. Emits start, success, failure, or skipped events.
Failure cascade. The levels nest: a step failure surfaces as a pipeline failure, which surfaces as an agent failure.
Subscriptions. Lifecycle events are grouped into message types. Each notifier configured under notifications subscribes to specific message types via message_types, so the same event stream can be routed to different channels at different levels of detail (e.g. failure to a low-noise human channel, progress to an API integration). When message_types is omitted, the default is [approvals, failure].
Delivery. Notifier delivery is asynchronous and best-effort within the agent. A notifier returning an error is logged but does not abort the agent or block other notifiers.
Pre-initialization failures. Failures that occur before the notification manager is constructed (cloud provider client setup, reading the root config from the bucket, parsing the notifications block itself) cannot be delivered through this system. Those are the responsibility of whatever runs the agent (Kubernetes Job, AWS CodeBuild, Cloud Run Job, etc.) via process exit code and container logs.
Message types
started— the agent execution has started. Fires once at the beginning of the execution, after the notification manager is constructed. Includes the command and the agent's cloud identifier.success— the agent execution finished successfully. Fires once at the end of a successful execution.failure— an agent-level failure. Fires once on any error reachable after the notification manager has been constructed (resource setup, encryption setup, updater construction, or a propagated pipeline failure). Includes the error message.progress— pipeline and step lifecycle. Carries:- Pipeline
starting/success/failurefor each release iteration, with the source versions being applied. - Step
starting/success/failure/skippedfor each configuration step. A step isskippedwhen no changed modules are found.
- Pipeline
approvals— the pipeline is waiting for manual approval. Includes the planned changes and a link to the pipeline. Also fires when an approval is granted.modules— list of modules that will be applied across all steps. Fires once near the start of the agent execution.sources— list of sources and their resolved releases. Fires once at the start of the release loop.schedule— emitted when the agent's update schedule is added, modified, or removed during bootstrap.
API
When configuring API notifications, the agent will send requests to the specified URL. The OpenAPI specification for the endpoints is in the openapi/notification-api.yaml.
Encryption
Agent uses default cloud provider encryption settings if no encryption module is present in config.
Currently, infralib only supports customer provided encryption in AWS with KMS. When KMS module is present in the config file, agent will use the KMS arn from the module OpenTofu output to configure the S3 bucket and CloudWatch log groups to use KMS by default. Agent will also use the KMS when creating Parameter Store parameters and Secret Manager secrets. Agent applies those changes only when a previous execution has successfully applied the KMS module. Meaning, only objects that have been put in S3 after the KMS module was applied will be encrypted with it.
Oracle Cloud manages encryption differently: the agent provisions and owns its own KMS vault and key automatically and uses it to encrypt the state bucket and every Vault-stored parameter and secret. It does not consume a KMS module from the config (the encryption module and customer-provided key apply to AWS only), so no encryption configuration is required.
Scheduling
Agent supports scheduling agent CodePipeline/Cloud Run Job executions by configuring the schedule section in the config file.
bootstrap command must be executed initially to create the required agent jobs.
Cron expressions must be in UTC timezone and valid according to the selected cloud provider. Removing the expression will also remove the scheduled execution.
AWS
Uses EventBridge Scheduler. Cron expression format is Minutes Hours Day-of-month Month Day-of-week Year.
Initial creation of schedule requires admin privileges to create the required role that can start the CodePipeline execution. Subsequent updates can be also be done with a generated service account.
GCloud
Uses Google Cloud Scheduler. Uses unix-cron format Minutes Hours Day-of-month Month Day-of-week.
Scheduler doesn't support all Cloud locations. Agent will try to use the configured location. If not supported, agent will use a fallback location based on the region:
| Region Prefix | Fallback Location |
|---|---|
| africa | europe-west1 |
| asia | asia-east1 |
| australia | australia-southeast1 |
| europe | europe-west1 |
| me | me-central2 |
| northamerica | northamerica-northeast1 |
| southamerica | southamerica-east1 |
| us | us-central1 |
Supported locations can change in the future. If configured location starts supporting scheduler then agent will create a new schedule in that location. Older schedule must be manually removed, otherwise both schedules will start Job executions.
Oracle
Scheduling is not yet supported for Oracle Cloud. A configured update_cron is ignored with a warning; run the agent's update command on an external schedule (e.g. a cron job or CI pipeline) instead.