1package envoy
2
3// BootstrapTplArgs is the set of arguments that may be interpolated into the
4// Envoy bootstrap template.
5type BootstrapTplArgs struct {
6	GRPC
7
8	// ProxyCluster is the cluster name for the the Envoy `node` specification and
9	// is typically the same as the ProxyID.
10	ProxyCluster string
11
12	// ProxyID is the ID of the proxy service instance as registered with the
13	// local Consul agent. This must be used as the Envoy `node.id` in order for
14	// the agent to deliver the correct configuration.
15	ProxyID string
16
17	// ProxySourceService is the Consul service name to report for this proxy
18	// instance's source service label. For sidecars it should be the
19	// Proxy.DestinationServiceName. For gateways and similar it is the service
20	// name of the proxy service itself.
21	ProxySourceService string
22
23	// AgentCAPEM is the CA to use to verify the local agent gRPC service if
24	// TLS is enabled.
25	AgentCAPEM string
26
27	// AdminAccessLogPath The path to write the access log for the
28	// administration server. If no access log is desired specify
29	// "/dev/null". By default it will use "/dev/null".
30	AdminAccessLogPath string
31
32	// AdminBindAddress is the address the Envoy admin server should bind to.
33	AdminBindAddress string
34
35	// AdminBindPort is the port the Envoy admin server should bind to.
36	AdminBindPort string
37
38	// LocalAgentClusterName is the name reserved for the local Consul agent gRPC
39	// service and is expected to be used for that purpose.
40	LocalAgentClusterName string
41
42	// Token is the Consul ACL token provided which is required to make gRPC
43	// discovery requests. If non-empty, this must be configured as the gRPC
44	// service "initial_metadata" with the key "x-consul-token" in order to
45	// authorize the discovery streaming RPCs.
46	Token string
47
48	// StaticClustersJSON is JSON string, each is expected to be a valid Cluster
49	// definition. They are appended to the "static_resources.clusters" list. Note
50	// that cluster names should be chosen in such a way that they won't collide
51	// with service names since we use plain service names as cluster names in xDS
52	// to make metrics population simpler and cluster names mush be unique. See
53	// https://www.envoyproxy.io/docs/envoy/v1.9.0/api-v2/api/v2/cds.proto.
54	StaticClustersJSON string
55
56	// StaticListenersJSON is a JSON string containing zero or more Listener
57	// definitions. They are appended to the "static_resources.listeners" list. A
58	// single listener should be given as a plain object, if more than one is to
59	// be added, they should be separated by a comma suitable for direct injection
60	// into a JSON array.
61	// See https://www.envoyproxy.io/docs/envoy/v1.9.0/api-v2/api/v2/lds.proto.
62	StaticListenersJSON string
63
64	// StatsSinksJSON is a JSON string containing an array in the right format
65	// to be rendered as the body of the `stats_sinks` field at the top level of
66	// the bootstrap config. It's format may vary based on Envoy version used. See
67	// https://www.envoyproxy.io/docs/envoy/v1.9.0/api-v2/config/metrics/v2/stats.proto#config-metrics-v2-statssink.
68	StatsSinksJSON string
69
70	// StatsConfigJSON is a JSON string containing an object in the right format
71	// to be rendered as the body of the `stats_config` field at the top level of
72	// the bootstrap config. It's format may vary based on Envoy version used. See
73	// https://www.envoyproxy.io/docs/envoy/v1.9.0/api-v2/config/metrics/v2/stats.proto#envoy-api-msg-config-metrics-v2-statsconfig.
74	StatsConfigJSON string
75
76	// StatsFlushInterval is the time duration between Envoy stats flushes. It is
77	// in proto3 "duration" string format for example "1.12s" See
78	// https://developers.google.com/protocol-buffers/docs/proto3#json and
79	// https://www.envoyproxy.io/docs/envoy/v1.9.0/api-v2/config/bootstrap/v2/bootstrap.proto#bootstrap
80	StatsFlushInterval string
81
82	// TracingConfigJSON is a JSON string containing an object in the right format
83	// to be rendered as the body of the `tracing` field at the top level of
84	// the bootstrap config. It's format may vary based on Envoy version used.
85	// See https://www.envoyproxy.io/docs/envoy/v1.9.0/api-v2/config/trace/v2/trace.proto.
86	TracingConfigJSON string
87
88	// Namespace is the Consul Enterprise Namespace of the proxy service instance
89	// as registered with the Consul agent.
90	Namespace string
91
92	// Datacenter is the datacenter where the proxy service instance is registered.
93	Datacenter string
94
95	// EnvoyVersion is the envoy version, which is necessary to generate the
96	// correct configuration.
97	EnvoyVersion string
98
99	// PrometheusBackendPort will configure a "prometheus_backend" cluster which
100	// envoy_prometheus_bind_addr will point to.
101	PrometheusBackendPort string
102
103	// PrometheusScrapePath will configure the path where metrics are exposed on
104	// the envoy_prometheus_bind_addr listener.
105	PrometheusScrapePath string
106}
107
108// GRPC settings used in the bootstrap template.
109type GRPC struct {
110	// AgentAddress is the IP address of the local agent where the proxy instance
111	// is registered.
112	AgentAddress string
113
114	// AgentPort is the gRPC port exposed on the local agent.
115	AgentPort string
116
117	// AgentTLS is true if the local agent gRPC service should be accessed over
118	// TLS.
119	AgentTLS bool
120
121	// AgentSocket is the path to a Unix Socket for communicating with the
122	// local agent's gRPC endpoint. Disabled if the empty (the default),
123	// but overrides AgentAddress and AgentPort if set.
124	AgentSocket string
125}
126
127// bootstrapTemplate sets '"ignore_health_on_host_removal": false' JUST to force this to be detected as a v3 bootstrap
128// config.
129const bootstrapTemplate = `{
130  "admin": {
131    "access_log_path": "{{ .AdminAccessLogPath }}",
132    "address": {
133      "socket_address": {
134        "address": "{{ .AdminBindAddress }}",
135        "port_value": {{ .AdminBindPort }}
136      }
137    }
138  },
139  "node": {
140    "cluster": "{{ .ProxyCluster }}",
141    "id": "{{ .ProxyID }}",
142    "metadata": {
143      "namespace": "{{if ne .Namespace ""}}{{ .Namespace }}{{else}}default{{end}}",
144      "envoy_version": "{{ .EnvoyVersion }}"
145    }
146  },
147  "static_resources": {
148    "clusters": [
149      {
150        "name": "{{ .LocalAgentClusterName }}",
151        "ignore_health_on_host_removal": false,
152        "connect_timeout": "1s",
153        "type": "STATIC",
154        {{- if .AgentTLS -}}
155        "transport_socket": {
156          "name": "tls",
157          "typed_config": {
158            "@type": "type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext",
159            "common_tls_context": {
160              "validation_context": {
161                "trusted_ca": {
162                  "inline_string": "{{ .AgentCAPEM }}"
163                }
164              }
165            }
166          }
167        },
168        {{- end }}
169        "http2_protocol_options": {},
170        "loadAssignment": {
171          "clusterName": "{{ .LocalAgentClusterName }}",
172          "endpoints": [
173            {
174              "lbEndpoints": [
175                {
176                  "endpoint": {
177                    "address": {
178                      {{- if .AgentSocket -}}
179                      "pipe": {
180                        "path": "{{ .AgentSocket }}"
181                      }
182                      {{- else -}}
183                      "socket_address": {
184                        "address": "{{ .AgentAddress }}",
185                        "port_value": {{ .AgentPort }}
186                      }
187                      {{- end -}}
188                    }
189                  }
190                }
191              ]
192            }
193          ]
194        }
195      }
196      {{- if .StaticClustersJSON -}}
197      ,
198      {{ .StaticClustersJSON }}
199      {{- end }}
200    ]{{- if .StaticListenersJSON -}}
201    ,
202    "listeners": [
203      {{ .StaticListenersJSON }}
204    ]
205    {{- end }}
206  },
207  {{- if .StatsSinksJSON }}
208  "stats_sinks": {{ .StatsSinksJSON }},
209  {{- end }}
210  {{- if .StatsConfigJSON }}
211  "stats_config": {{ .StatsConfigJSON }},
212  {{- end }}
213  {{- if .StatsFlushInterval }}
214  "stats_flush_interval": "{{ .StatsFlushInterval }}",
215  {{- end }}
216  {{- if .TracingConfigJSON }}
217  "tracing": {{ .TracingConfigJSON }},
218  {{- end }}
219  "dynamic_resources": {
220    "lds_config": {
221      "ads": {},
222      "resource_api_version": "V3"
223    },
224    "cds_config": {
225      "ads": {},
226      "resource_api_version": "V3"
227    },
228    "ads_config": {
229      "api_type": "DELTA_GRPC",
230      "transport_api_version": "V3",
231      "grpc_services": {
232        "initial_metadata": [
233          {
234            "key": "x-consul-token",
235            "value": "{{ .Token }}"
236          }
237        ],
238        "envoy_grpc": {
239          "cluster_name": "{{ .LocalAgentClusterName }}"
240        }
241      }
242    }
243  }
244}
245`
246