envoyproxy / envoy

Cloud-native high-performance edge/middle/service proxy
https://www.envoyproxy.io
Apache License 2.0
24.76k stars 4.76k forks source link

Not able to extend a yaml anchor in config file #12926

Open drunkirishcoder opened 4 years ago

drunkirishcoder commented 4 years ago

Title: Not able to extend a yaml anchor in config file

Description:

The yaml config parser of Envoy seems to support anchors. But it doesn't support merging keys from the anchors. For example the following works

access_log:
- name: envoy.access_loggers.file
  typed_config:
    "@type": type.googleapis.com/envoy.extensions.access_loggers.file.v3.FileAccessLog
    path: "/dev/stdout"
    typed_json_format: &json_format
      timestamp: "%START_TIME%"
      level: info
...
...
...
access_log:
- name: envoy.access_loggers.file
  typed_config:
    "@type": type.googleapis.com/envoy.extensions.access_loggers.file.v3.FileAccessLog
    path: "/dev/stdout"
    typed_json_format: *json_format

but this doesn't work

access_log:
- name: envoy.access_loggers.file
  typed_config:
    "@type": type.googleapis.com/envoy.extensions.access_loggers.file.v3.FileAccessLog
    path: "/dev/stdout"
    typed_json_format: &json_format
      timestamp: "%START_TIME%"
      level: info
...
...
...
access_log:
- name: envoy.access_loggers.file
  typed_config:
    "@type": type.googleapis.com/envoy.extensions.access_loggers.file.v3.FileAccessLog
    path: "/dev/stdout"
    typed_json_format:
      <<: *json_format
      level: warn

it produces

{
  "<<": {
    "timestamp": "2020-09-01T19:11:23.085Z",
    "level": "info"
  },
  "level": "warn"
}

the expected log output is

{
  "timestamp": "2020-09-01T19:11:23.085Z",
  "level": "warn"
}

Config:

Include the config used to configure Envoy.

admin:
  access_log_path: "/var/log/envoy/admin.log"
  address:
    socket_address:
      address: 0.0.0.0
      port_value: 9000
static_resources:
  listeners:
  - address:
      socket_address:
        address: 0.0.0.0
        port_value: 9080
    traffic_direction: INBOUND
    filter_chains:
    - filters:
      - name: envoy.filters.network.http_connection_manager
        typed_config:
          "@type": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager
          codec_type: auto
          stat_prefix: ingress_http
          use_remote_address: true
          route_config:
            name: reverse_proxy
            virtual_hosts:
            - name: ingress_http
              domains: ["*"]
              routes:
              - match:
                  prefix: "/"
                route:
                  cluster: reverse_proxy_cluster
          http_filters:
          - name: envoy.filters.http.router
            typed_config:
              "@type": type.googleapis.com/envoy.extensions.filters.http.router.v3.Router
          access_log:
          - name: envoy.access_loggers.file
            typed_config:
              "@type": type.googleapis.com/envoy.extensions.access_loggers.file.v3.FileAccessLog
              path: "/dev/stdout"
              typed_json_format: &json_format
                "@timestamp": "%START_TIME%"
                ecs:
                  version: "1.5"
                log:
                  level: "info"  # default envoy log level
                service:
                  name: "my-service"
                  version: "1.0"
                host:
                  hostname: "%HOSTNAME%"
                http:
                  version: "%PROTOCOL%"
                  request:
                    method: "%REQ(:METHOD)%"
                    duration: "%DURATION%"
                    body:
                      bytes: "%BYTES_RECEIVED%"
                    headers:  # not in ECS
                      id: "%REQ(X-REQUEST-ID)%"
                      authority: "%REQ(:AUTHORITY)%"
                      x_forwarded_for: "%REQ(X-FORWARDED-FOR)%"
                  response:
                    status_code: "%RESPONSE_CODE%"
                    flags: "%RESPONSE_FLAGS%"
                    body:
                      bytes: "%BYTES_SENT%"
                user_agent:
                  name: "%REQ(USER-AGENT)%"
                url:
                  path: "%REQ(X-ENVOY-ORIGINAL-PATH?:PATH)%"
                client:
                  address: "%DOWNSTREAM_REMOTE_ADDRESS%"
                server:
                  address: "%UPSTREAM_HOST%"
                network:
                  direction: "inbound"
  - address:
      socket_address:
        address: 0.0.0.0
        port_value: 9090
    traffic_direction: OUTBOUND
    filter_chains:
    - 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: egress_http
          route_config:
            name: forward_proxy
            virtual_hosts:
            - name: egress_http
              domains: ["*"]
              routes:
              - match:
                  prefix: "/"
                route:
                  cluster: forward_proxy_cluster
          http_filters:
          - name: envoy.filters.http.dynamic_forward_proxy
            typed_config:
              "@type": type.googleapis.com/envoy.config.filter.http.dynamic_forward_proxy.v2alpha.FilterConfig
              dns_cache_config:
                name: forward_proxy_cache_config
                dns_lookup_family: V4_ONLY
          - name: envoy.filters.http.router
            typed_config:
              "@type": type.googleapis.com/envoy.extensions.filters.http.router.v3.Router
          access_log:
          - name: envoy.access_loggers.file
            typed_config:
              "@type": type.googleapis.com/envoy.extensions.access_loggers.file.v3.FileAccessLog
              path: "/dev/stdout"
              typed_json_format:
                <<: *json_format
                network:
                  direction: "outbound"
  clusters:
  - name: reverse_proxy_cluster
    connect_timeout: 0.25s
    type: strict_dns
    lb_policy: ROUND_ROBIN
    load_assignment:
      cluster_name: reverse_proxy_cluster
      endpoints:
      - lb_endpoints:
        - endpoint:
            address:
              socket_address:
                address: 127.0.0.1
                port_value: 8080
  - name: forward_proxy_cluster
    connect_timeout: 1s
    lb_policy: CLUSTER_PROVIDED
    cluster_type:
      name: envoy.clusters.dynamic_forward_proxy
      typed_config:
        "@type": type.googleapis.com/envoy.extensions.clusters.dynamic_forward_proxy.v3.ClusterConfig
        dns_cache_config:
          name: forward_proxy_cache_config
          dns_lookup_family: V4_ONLY
    transport_socket:
      name: envoy.transport_sockets.tls
      typed_config:
        "@type": type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext
        common_tls_context:
          validation_context:
            trusted_ca: {filename: /etc/ssl/certs/ca-certificates.crt}
snowp commented 4 years ago

This probably needs someone to dig into whether this is a yaml-cpp issue or if there is something that can be done on the Envoy side to support this.

drunkirishcoder commented 4 years ago

@snowp it's indeed an yaml-cpp problem. Doesn't look like they want to support this because it's not in the official 1.2 spec. That's quite unfortunate. I guess this is not an Envoy problem per se.