I am using templatefile to generate an envoy config file. When I indent my for loops the first line after the loop declaration has extra spaces resulting in a malformed yaml file. It seems it is adding all of the spaces that are used to indent the for loop to the first line of text within the loop. The same thing is happening with if statements. If I remove all spaces before the loop or if statement everything is generated correctly.
I've made sure the indentation is consistent for the loop and if statement begin/end blocks. I've checked for hidden indentation characters like \t
.
I will just remove the spaces before the loop and if statements if that's what's needed, but I would like to indent the loops and if statements to make the code easier to read. Especially when the config gets more complicated. Am I doing something wrong here, or any advice to fix it?
This template adds extra spaces:
static_resources:
listeners:
- name: listener_0
address:
socket_address:
address: 0.0.0.0
port_value: 10000
listener_filters:
- name: "envoy.filters.listener.tls_inspector"
typed_config:
"@type": type.googleapis.com/envoy.extensions.filters.listener.tls_inspector.v3.TlsInspector
filter_chains:
%{ for filter_chain_match in filter_chain_matches ~}
- filter_chain_match:
server_names: ${jsonencode(filter_chain_match.server_names)}
filters:
- name: envoy.filters.network.http_connection_manager
typed_config:
"@type": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager
stat_prefix: ingress_http
access_log:
- name: envoy.access_loggers.stdout
typed_config:
"@type": type.googleapis.com/envoy.extensions.access_loggers.stream.v3.StdoutAccessLog
set_current_client_cert_details:
subject: true
http_filters:
- name: envoy.filters.http.router
typed_config:
"@type": type.googleapis.com/envoy.extensions.filters.http.router.v3.Router
route_config:
name: local_route
virtual_hosts:
- name: local_service
domains: ["*"]
routes:
- match:
prefix: "/"
route:
cluster: ${cluster}
transport_socket:
name: envoy.transport_sockets.tls
typed_config:
"@type": type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext
require_client_certificate: ${filter_chain_match.require_client_certificate}
common_tls_context:
tls_certificates:
- certificate_chain:
filename: ${filter_chain_match.server_cert_chain_path}
private_key:
filename: ${filter_chain_match.server_private_key_path}
%{ if filter_chain_match.require_client_certificate ~}
validation_context:
trusted_ca:
filename: ${filter_chain_match.trusted_ca_path}
%{ for allowed_subject_alt_name in filter_chain_match.allowed_subject_alt_names ~}
match_typed_subject_alt_names:
- san_type: ${allowed_subject_alt_name.san_type}
matcher:
${allowed_subject_alt_name.matcher_type}: ${allowed_subject_alt_name.san}
%{ endfor ~}
%{ endif ~}
%{ endfor ~}
clusters:
- name: ${cluster}
connect_timeout: 30s
type: LOGICAL_DNS
dns_lookup_family: V4_ONLY
load_assignment:
cluster_name: ${cluster}
endpoints:
- lb_endpoints:
- endpoint:
address:
socket_address:
address: ${cluster_ip}
port_value: 443
transport_socket:
name: envoy.transport_sockets.tls
typed_config:
"@type": type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext
Here is an example of the malformed yaml from the template above. Note the extra spaces before elements such as - filter_chain_match
.
static_resources:
listeners:
- name: listener_0
address:
socket_address:
address: 0.0.0.0
port_value: 10000
listener_filters:
- name: "envoy.filters.listener.tls_inspector"
typed_config:
"@type": type.googleapis.com/envoy.extensions.filters.listener.tls_inspector.v3.TlsInspector
filter_chains:
- filter_chain_match:
server_names: ["api.mydomain.com"]
filters:
- name: envoy.filters.network.http_connection_manager
typed_config:
"@type": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager
stat_prefix: ingress_http
access_log:
- name: envoy.access_loggers.stdout
typed_config:
"@type": type.googleapis.com/envoy.extensions.access_loggers.stream.v3.StdoutAccessLog
set_current_client_cert_details:
subject: true
http_filters:
- name: envoy.filters.http.router
typed_config:
"@type": type.googleapis.com/envoy.extensions.filters.http.router.v3.Router
route_config:
name: local_route
virtual_hosts:
- name: local_service
domains: ["*"]
routes:
- match:
prefix: "/"
route:
cluster: my_cluster
transport_socket:
name: envoy.transport_sockets.tls
typed_config:
"@type": type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext
require_client_certificate: true
common_tls_context:
tls_certificates:
- certificate_chain:
filename: /path/to/server/cert.pem
private_key:
filename: /path/to/server/key.pem
validation_context:
trusted_ca:
filename: /path/to/trusted/cacert.pem
match_typed_subject_alt_names:
- san_type: DNS
matcher:
exact: my-api-client-one.somedomain.com
match_typed_subject_alt_names:
- san_type: DNS
matcher:
exact: api-client-two.anotherdomain.com
clusters:
- name: my_cluster
connect_timeout: 30s
type: LOGICAL_DNS
dns_lookup_family: V4_ONLY
load_assignment:
cluster_name: my_cluster
endpoints:
- lb_endpoints:
- endpoint:
address:
socket_address:
address: 10.0.0.5
port_value: 443
transport_socket:
name: envoy.transport_sockets.tls
typed_config:
"@type": type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext
This template renders valid yaml with the correct indentation:
static_resources:
listeners:
- name: listener_0
address:
socket_address:
address: 0.0.0.0
port_value: 10000
listener_filters:
- name: "envoy.filters.listener.tls_inspector"
typed_config:
"@type": type.googleapis.com/envoy.extensions.filters.listener.tls_inspector.v3.TlsInspector
filter_chains:
%{ for filter_chain_match in filter_chain_matches ~}
- filter_chain_match:
server_names: ${jsonencode(filter_chain_match.server_names)}
filters:
- name: envoy.filters.network.http_connection_manager
typed_config:
"@type": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager
stat_prefix: ingress_http
access_log:
- name: envoy.access_loggers.stdout
typed_config:
"@type": type.googleapis.com/envoy.extensions.access_loggers.stream.v3.StdoutAccessLog
set_current_client_cert_details:
subject: true
http_filters:
- name: envoy.filters.http.router
typed_config:
"@type": type.googleapis.com/envoy.extensions.filters.http.router.v3.Router
route_config:
name: local_route
virtual_hosts:
- name: local_service
domains: ["*"]
routes:
- match:
prefix: "/"
route:
cluster: ${cluster}
transport_socket:
name: envoy.transport_sockets.tls
typed_config:
"@type": type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext
require_client_certificate: ${filter_chain_match.require_client_certificate}
common_tls_context:
tls_certificates:
- certificate_chain:
filename: ${filter_chain_match.server_cert_chain_path}
private_key:
filename: ${filter_chain_match.server_private_key_path}
%{ if filter_chain_match.require_client_certificate ~}
validation_context:
trusted_ca:
filename: ${filter_chain_match.trusted_ca_path}
%{ for allowed_subject_alt_name in filter_chain_match.allowed_subject_alt_names ~}
match_typed_subject_alt_names:
- san_type: ${allowed_subject_alt_name.san_type}
matcher:
${allowed_subject_alt_name.matcher_type}: ${allowed_subject_alt_name.san}
%{ endfor ~}
%{ endif ~}
%{ endfor ~}
clusters:
- name: ${cluster}
connect_timeout: 30s
type: LOGICAL_DNS
dns_lookup_family: V4_ONLY
load_assignment:
cluster_name: ${cluster}
endpoints:
- lb_endpoints:
- endpoint:
address:
socket_address:
address: ${cluster_ip}
port_value: 443
transport_socket:
name: envoy.transport_sockets.tls
typed_config:
"@type": type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext
I'm using Terraform v1.6.6.