#
# Licensed to the Apache Software Foundation (ASF) under one or more
# contributor license agreements.  See the NOTICE file distributed with
# this work for additional information regarding copyright ownership.
# The ASF licenses this file to You under the Apache License, Version 2.0
# (the "License"); you may not use this file except in compliance with
# the License.  You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

apiVersion: v1
kind: ConfigMap
metadata:
  name: {{ include "apisix.fullname" . }}
  namespace: {{ .Release.Namespace }}
data:
  config.yaml: |-
    #
    # Licensed to the Apache Software Foundation (ASF) under one or more
    # contributor license agreements.  See the NOTICE file distributed with
    # this work for additional information regarding copyright ownership.
    # The ASF licenses this file to You under the Apache License, Version 2.0
    # (the "License"); you may not use this file except in compliance with
    # the License.  You may obtain a copy of the License at
    #
    #     http://www.apache.org/licenses/LICENSE-2.0
    #
    # Unless required by applicable law or agreed to in writing, software
    # distributed under the License is distributed on an "AS IS" BASIS,
    # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    # See the License for the specific language governing permissions and
    # limitations under the License.
    #
    {{- if .Values.apisix.fullCustomConfig.enabled }}
    {{- range $key, $value := .Values.apisix.fullCustomConfig.config }}
    {{ $key }}:
      {{- include "apisix.tplvalues.render" (dict "value" $value "context" $) | nindent 6 }}
    {{- end }}
    {{- else }}
    apisix:    # universal configurations
      {{- if not (eq .Values.apisix.deployment.role "control_plane") }}
      node_listen:    # APISIX listening port
        - {{ .Values.service.http.containerPort }}
        {{- with .Values.service.http.additionalContainerPorts }}
        {{- toYaml . | nindent 8}}
        {{- end }}
      {{- end }}
      enable_heartbeat: true
      enable_admin: {{ .Values.apisix.admin.enabled }}
      enable_admin_cors: {{ .Values.apisix.admin.cors }}
      enable_debug: false
      {{- if or .Values.apisix.customPlugins.enabled .Values.apisix.luaModuleHook.enabled }}
      extra_lua_path: {{ .Values.apisix.customPlugins.luaPath }};{{ .Values.apisix.luaModuleHook.luaPath }}
      {{- end }}

      enable_control: {{ .Values.control.enabled }}
      {{- if .Values.control.enabled }}
      control:
        ip: {{ default "127.0.0.1" .Values.control.service.ip }}
        port: {{ default 9090 .Values.control.service.port }}
      {{- end }}

      {{- if .Values.apisix.luaModuleHook.enabled }}
      lua_module_hook: {{ .Values.apisix.luaModuleHook.hookPoint | quote }}
      {{- end }}

      enable_dev_mode: false                       # Sets nginx worker_processes to 1 if set to true
      enable_reuseport: true                       # Enable nginx SO_REUSEPORT switch if set to true.
      enable_ipv6: {{ .Values.apisix.enableIPv6 }} # Enable nginx IPv6 resolver
      enable_http2: {{ .Values.apisix.enableHTTP2 }}
      enable_server_tokens: {{ .Values.apisix.enableServerTokens }} # Whether the APISIX version number should be shown in Server header

      # proxy_protocol:                   # Proxy Protocol configuration
      #   listen_http_port: 9181          # The port with proxy protocol for http, it differs from node_listen and admin_listen.
      #                                   # This port can only receive http request with proxy protocol, but node_listen & admin_listen
      #                                   # can only receive http request. If you enable proxy protocol, you must use this port to
      #                                   # receive http request with proxy protocol
      #   listen_https_port: 9182         # The port with proxy protocol for https
      #   enable_tcp_pp: true             # Enable the proxy protocol for tcp proxy, it works for stream_proxy.tcp option
      #   enable_tcp_pp_to_upstream: true # Enables the proxy protocol to the upstream server

      proxy_cache:                         # Proxy Caching configuration
        cache_ttl: 10s                     # The default caching time if the upstream does not specify the cache time
        zones:                             # The parameters of a cache
        - name: disk_cache_one             # The name of the cache, administrator can be specify
                                           # which cache to use by name in the admin api
          memory_size: 50m                 # The size of shared memory, it's used to store the cache index
          disk_size: 1G                    # The size of disk, it's used to store the cache data
          disk_path: "/tmp/disk_cache_one" # The path to store the cache data
          cache_levels: "1:2"              # The hierarchy levels of a cache
      #  - name: disk_cache_two
      #    memory_size: 50m
      #    disk_size: 1G
      #    disk_path: "/tmp/disk_cache_two"
      #    cache_levels: "1:2"

      router:
        http: {{ .Values.apisix.router.http }}  # radixtree_uri: match route by uri(base on radixtree)
                                    # radixtree_host_uri: match route by host + uri(base on radixtree)
                                    # radixtree_uri_with_parameter: match route by uri with parameters
        ssl: 'radixtree_sni'        # radixtree_sni: match route by SNI(base on radixtree)
      
      {{- $proxy_mode := "" }}
      {{- if and .Values.service.stream.enabled .Values.service.http.enabled }}
        {{- $proxy_mode = "http&stream" }}
      {{- else if .Values.service.http.enabled }}
        {{- $proxy_mode = "http" }}
      {{- else if .Values.service.stream.enabled }}
        {{- $proxy_mode = "stream" }}
      {{- end }}

      proxy_mode: {{ $proxy_mode }}

      {{- if or (index .Values "ingress-controller" "enabled") (and .Values.service.stream.enabled (or (gt (len .Values.service.stream.tcp) 0) (gt (len .Values.service.stream.udp) 0))) }}
      stream_proxy:                 # TCP/UDP proxy
        {{- if or (index .Values "ingress-controller" "enabled") (gt (len .Values.service.stream.tcp) 0) }}
        tcp:                        # TCP proxy port list
          {{- if gt (len .Values.service.stream.tcp) 0}}
          {{- range .Values.service.stream.tcp }}
          {{- if kindIs "map" . }}
          - addr: {{ .addr }}
          {{- if hasKey . "tls" }}
            tls: {{ .tls }}
          {{- end }}
          {{- else }}
          - {{ . }}
          {{- end }}
          {{- end }}
          {{- else}}
          - 9100
          {{- end }}
        {{- end }}
        {{- if or (index .Values "ingress-controller" "enabled") (gt (len .Values.service.stream.udp) 0) }}
        udp:                        # UDP proxy port list
          {{- if gt (len .Values.service.stream.udp) 0}}
          {{- range .Values.service.stream.udp }}
          - {{ . }}
          {{- end }}
          {{- else}}
          - 9200
          {{- end }}
        {{- end }}
      {{- end }}
      # dns_resolver:
      #   {{- range $resolver := .Values.apisix.dns.resolvers }}
      #   - {{ $resolver }}
      #   {{- end }}
      dns_resolver_valid: {{.Values.apisix.dns.validity}}
      resolver_timeout: {{.Values.apisix.dns.timeout}}
      ssl:
        enable: {{ .Values.apisix.ssl.enabled }}
        listen:
          - port: {{ .Values.apisix.ssl.containerPort }}
            enable_http3: {{ .Values.apisix.ssl.enableHTTP3 }}
          {{- with .Values.apisix.ssl.additionalContainerPorts }}
          {{- toYaml . | nindent 10}}
          {{- end }}
        ssl_protocols: {{ .Values.apisix.ssl.sslProtocols | quote }}
        ssl_ciphers: "ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:DHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA:ECDHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES256-SHA256:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:DES-CBC3-SHA"
        {{- if and .Values.apisix.ssl.enabled .Values.apisix.ssl.existingCASecret }}
        ssl_trusted_certificate: "/usr/local/apisix/conf/ssl/{{ .Values.apisix.ssl.certCAFilename }}"
        {{- end }}
        {{- if and .Values.apisix.ssl.enabled .Values.apisix.ssl.fallbackSNI }}
        fallback_sni: {{ .Values.apisix.ssl.fallbackSNI | quote }}
        {{- end }}

    nginx_config:    # config for render the template to genarate nginx.conf
      error_log: "{{ .Values.apisix.nginx.logs.errorLog }}"
      error_log_level: "{{ .Values.apisix.nginx.logs.errorLogLevel }}"    # warn,error
      worker_processes: "{{ .Values.apisix.nginx.workerProcesses }}"
      enable_cpu_affinity: {{ and true .Values.apisix.nginx.enableCPUAffinity }}
      worker_rlimit_nofile: {{ default "20480" .Values.apisix.nginx.workerRlimitNofile }}  # the number of files a worker process can open, should be larger than worker_connections
      event:
        worker_connections: {{ default "10620" .Values.apisix.nginx.workerConnections  }}
      {{- with .Values.apisix.nginx.envs }}
      envs:
      {{- range $env := . }}
        - {{ $env }}
      {{- end }}
      {{- end }}
      http:
        enable_access_log: {{ .Values.apisix.nginx.logs.enableAccessLog }}
        {{- if .Values.apisix.nginx.logs.enableAccessLog }}
        access_log: "{{ .Values.apisix.nginx.logs.accessLog }}"
        access_log_format: '{{ .Values.apisix.nginx.logs.accessLogFormat }}'
        access_log_format_escape: {{ .Values.apisix.nginx.logs.accessLogFormatEscape }}
        {{- end }}
        keepalive_timeout: {{ .Values.apisix.nginx.keepaliveTimeout | quote }}
        client_header_timeout: 60s     # timeout for reading client request header, then 408 (Request Time-out) error is returned to the client
        client_body_timeout: 60s       # timeout for reading client request body, then 408 (Request Time-out) error is returned to the client
        send_timeout: 10s              # timeout for transmitting a response to the client.then the connection is closed
        underscores_in_headers: "on"   # default enables the use of underscores in client request header fields
        real_ip_header: "X-Real-IP"    # http://nginx.org/en/docs/http/ngx_http_realip_module.html#real_ip_header
        real_ip_from:                  # http://nginx.org/en/docs/http/ngx_http_realip_module.html#set_real_ip_from
          - 127.0.0.1
          - 'unix:'
        {{- if .Values.apisix.nginx.customLuaSharedDicts }}
        custom_lua_shared_dict:        # add custom shared cache to nginx.conf
        {{- range $dict := .Values.apisix.nginx.customLuaSharedDicts }}
          {{ $dict.name }}: {{ $dict.size }}
        {{- end }}
        {{- end }}
      {{- if .Values.apisix.nginx.configurationSnippet.main }}
      main_configuration_snippet: {{- toYaml .Values.apisix.nginx.configurationSnippet.main | indent 6 }}
      {{- end }}
      {{- if .Values.apisix.nginx.configurationSnippet.httpStart }}
      http_configuration_snippet: {{- toYaml .Values.apisix.nginx.configurationSnippet.httpStart | indent 6 }}
      {{- end }}
      {{- if .Values.apisix.nginx.configurationSnippet.httpEnd }}
      http_end_configuration_snippet: {{- toYaml .Values.apisix.nginx.configurationSnippet.httpEnd | indent 6 }}
      {{- end }}
      {{- if .Values.apisix.nginx.configurationSnippet.httpSrv }}
      http_server_configuration_snippet: {{- toYaml .Values.apisix.nginx.configurationSnippet.httpSrv | indent 6 }}
      {{- end }}
      {{- if .Values.apisix.nginx.configurationSnippet.httpAdmin }}
      http_admin_configuration_snippet: {{ toYaml .Values.apisix.nginx.configurationSnippet.httpAdmin | indent 6 }}
      {{- end }}
      {{- if .Values.apisix.nginx.configurationSnippet.stream }}
      stream_configuration_snippet: {{- toYaml .Values.apisix.nginx.configurationSnippet.stream | indent 6 }}
      {{- end }}

    {{- if .Values.apisix.discovery.enabled }}
    discovery:
      {{- range $key, $value := .Values.apisix.discovery.registry }}
      {{- if $value }}
      {{ $key }}:
        {{- include "apisix.tplvalues.render" (dict "value" $value "context" $) | nindent 8 }}
      {{- else }}
      {{ $key }}: {}
      {{- end }}
      {{- end }}
    {{- end }}

    {{- if .Values.apisix.vault.enabled }}
    vault:
      host: {{ .Values.apisix.vault.host }}
      timeout: {{ .Values.apisix.vault.timeout }}
      token: {{ .Values.apisix.vault.token }}
      prefix: {{ .Values.apisix.vault.prefix }}
    {{- end }}

    {{- if .Values.apisix.plugins }}
    plugins:    # plugin list
    {{- range $plugin := .Values.apisix.plugins }}
      {{- if ne $plugin "" }}
      - {{ $plugin }}
      {{- end }}
    {{- end }}
    {{- if .Values.apisix.customPlugins.enabled }}
    {{- range $plugin := .Values.apisix.customPlugins.plugins }}
      - {{ $plugin.name }}
    {{- end }}
    {{- end }}
    {{- end }}
    {{- if .Values.apisix.stream_plugins }}
    stream_plugins:
    {{- range $plugin := .Values.apisix.stream_plugins }}
      {{- if ne $plugin "" }}
      - {{ $plugin }}
      {{- end }}
    {{- end }}
    {{- end }}

    {{- if .Values.apisix.extPlugin.enabled }}
    ext-plugin:
      cmd:
      {{- range $arg := .Values.apisix.extPlugin.cmd }}
        - {{ $arg }}
      {{- end }}
    {{- end }}

    {{- if or .Values.apisix.pluginAttrs .Values.apisix.customPlugins.enabled .Values.apisix.prometheus.enabled}}
    {{- $pluginAttrs := include "apisix.pluginAttrs" . -}}
    {{- if gt (len ($pluginAttrs | fromYaml)) 0 }}
    plugin_attr: {{- $pluginAttrs | nindent 6 }}
    {{- end }}
    {{- end }}

    {{- if .Values.apisix.wasm.enabled }}
    wasm:
      plugins:
        {{- toYaml .Values.apisix.wasm.plugins | nindent 8 }}
    {{- end }}

    deployment:
      role: {{ .Values.apisix.deployment.role }}

      {{- if eq .Values.apisix.deployment.role "traditional" }}
      role_traditional:
        config_provider: etcd
      {{- end }}

      {{- if eq .Values.apisix.deployment.role "control_plane" }}
      role_control_plane:
        config_provider: etcd
      {{- end }}

      {{- if eq .Values.apisix.deployment.role "data_plane" }}
      role_data_plane:
        config_provider: {{- eq .Values.apisix.deployment.mode "standalone" | ternary "yaml" "etcd" | indent 1 }}
      {{- end }}

      {{- if not (eq .Values.apisix.deployment.role "data_plane") }}
      admin:
        allow_admin:    # http://nginx.org/en/docs/http/ngx_http_access_module.html#allow
        {{- if .Values.apisix.admin.allow.ipList }}
        {{- range $ips := .Values.apisix.admin.allow.ipList }}
          - {{ $ips }}
        {{- end }}
        {{- else }}
          - 0.0.0.0/0
        {{- end}}
        {{- if or (index .Values "ingress-controller" "enabled") .Values.dashboard.enabled  }}
          - 0.0.0.0/0
        {{- end}}
        #   - "::/64"
        {{- if .Values.apisix.admin.enabled }}
        admin_listen:
          ip: {{ .Values.apisix.admin.ip }}
          port: {{ .Values.apisix.admin.port }}
        {{- end }}
        # Default token when use API to call for Admin API.
        # *NOTE*: Highly recommended to modify this value to protect APISIX's Admin API.
        # Disabling this configuration item means that the Admin API does not
        # require any authentication.
        admin_key:
          # admin: can everything for configuration data
          - name: "admin"
            {{- if .Values.apisix.admin.credentials.secretName }}
            key: ${{"{{"}}APISIX_ADMIN_KEY{{"}}"}}
            {{- else }}
            key: {{ .Values.apisix.admin.credentials.admin }}
            {{- end }}
            role: admin
          # viewer: only can view configuration data
          - name: "viewer"
            {{- if .Values.apisix.admin.credentials.secretName }}
            key: ${{"{{"}}APISIX_VIEWER_KEY{{"}}"}}
            {{- else }}
            key: {{ .Values.apisix.admin.credentials.viewer }}
            {{- end }}
            role: viewer
      {{- end }}
      {{- if not (eq .Values.apisix.deployment.mode "standalone")}}
      etcd:
      {{- if .Values.etcd.enabled }}
        host:                          # it's possible to define multiple etcd hosts addresses of the same etcd cluster.
          {{- if .Values.etcd.fullnameOverride }}
          - "{{ include "apisix.etcd.auth.scheme" . }}://{{ .Values.etcd.fullnameOverride }}:{{ .Values.etcd.service.port }}"
          {{- else }}
          - "{{ include "apisix.etcd.auth.scheme" . }}://{{ .Release.Name }}-etcd.{{ .Release.Namespace }}.svc.{{ .Values.etcd.clusterDomain }}:{{ .Values.etcd.service.port }}"
          {{- end}}
      {{- else }}
        host:                          # it's possible to define multiple etcd hosts addresses of the same etcd cluster.
          {{- range $value := .Values.externalEtcd.host }}
          - "{{ $value }}"             # multiple etcd address
          {{- end}}
      {{- end }}
        prefix: {{ .Values.etcd.prefix | quote }}    # configuration prefix in etcd
        timeout: {{ .Values.etcd.timeout }}    # 30 seconds
        {{- if and (not .Values.etcd.enabled) .Values.externalEtcd.user }}
        user: {{ .Values.externalEtcd.user | quote }}
        password: "{{ print "${{ APISIX_ETCD_PASSWORD }}" }}"
        {{- else if and .Values.etcd.enabled .Values.etcd.auth.rbac.create }}
        user: "root"
        password: "{{ print "${{APISIX_ETCD_PASSWORD}}" }}"
        {{- end }}
        {{- if .Values.etcd.auth.tls.enabled }}
        tls:
          cert: "/etcd-ssl/{{ .Values.etcd.auth.tls.certFilename }}"
          key: "/etcd-ssl/{{ .Values.etcd.auth.tls.certKeyFilename }}"
          verify: {{ .Values.etcd.auth.tls.verify }}
          sni: "{{ .Values.etcd.auth.tls.sni }}"
        {{- end }}
      {{- end }}
      {{- end }}
     
