agones.dev/agones@v1.53.0/install/helm/agones/templates/service/allocation.yaml (about) 1 # Copyright 2019 Google LLC All Rights Reserved. 2 # 3 # Licensed under the Apache License, Version 2.0 (the "License"); 4 # you may not use this file except in compliance with the License. 5 # You may obtain a copy of the License at 6 # 7 # http://www.apache.org/licenses/LICENSE-2.0 8 # 9 # Unless required by applicable law or agreed to in writing, software 10 # distributed under the License is distributed on an "AS IS" BASIS, 11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 # See the License for the specific language governing permissions and 13 # limitations under the License. 14 15 {{- $useLoadBalancerIP := and (ne .Values.agones.allocator.service.loadBalancerIP "") (eq .Values.agones.allocator.service.serviceType "LoadBalancer") }} 16 {{- if .Values.agones.allocator.install }} 17 # Define a Service for the agones-allocator 18 apiVersion: v1 19 kind: Service 20 metadata: 21 name: {{ $.Values.agones.allocator.service.name }} 22 namespace: {{ .Release.Namespace }} 23 labels: 24 component: allocator 25 app: {{ template "agones.name" . }} 26 chart: {{ template "agones.chart" . }} 27 release: {{ .Release.Name }} 28 heritage: {{ .Release.Service }} 29 {{- if .Values.agones.allocator.service.annotations }} 30 annotations: 31 {{ toYaml .Values.agones.allocator.service.annotations | indent 4 }} 32 {{- end }} 33 spec: 34 selector: 35 multicluster.agones.dev/role: allocator 36 {{- if .Values.agones.allocator.service.ipFamilyPolicy }} 37 ipFamilyPolicy: {{ .Values.agones.allocator.service.ipFamilyPolicy }} 38 {{- end }} 39 {{- if .Values.agones.allocator.service.ipFamilies }} 40 ipFamilies: {{ toYaml .Values.agones.allocator.service.ipFamilies | nindent 4 }} 41 {{- end }} 42 ports: 43 {{- if .Values.agones.allocator.service.http.enabled }} 44 - port: {{ .Values.agones.allocator.service.http.port }} 45 name: {{ .Values.agones.allocator.service.http.portName }} 46 targetPort: {{ .Values.agones.allocator.service.http.targetPort }} 47 {{- if .Values.agones.allocator.service.http.appProtocol }} 48 appProtocol: {{.Values.agones.allocator.service.http.appProtocol}} 49 {{- end}} 50 {{- if eq .Values.agones.allocator.service.serviceType "NodePort" }} 51 nodePort: {{ .Values.agones.allocator.service.http.nodePort }} 52 {{- end }} 53 protocol: TCP 54 {{- if .Values.agones.allocator.service.grpc.enabled }} 55 {{- if ne .Values.agones.allocator.service.grpc.port .Values.agones.allocator.service.http.port }} 56 - port: {{ .Values.agones.allocator.service.grpc.port }} 57 name: {{ .Values.agones.allocator.service.grpc.portName }} 58 targetPort: {{ .Values.agones.allocator.service.grpc.targetPort }} 59 {{- if .Values.agones.allocator.service.grpc.appProtocol }} 60 appProtocol: {{.Values.agones.allocator.service.grpc.appProtocol}} 61 {{- end}} 62 {{- if eq .Values.agones.allocator.service.serviceType "NodePort" }} 63 nodePort: {{ .Values.agones.allocator.service.grpc.nodePort }} 64 {{- end }} 65 protocol: TCP 66 {{- end }} 67 {{- end }} 68 {{- else if .Values.agones.allocator.service.grpc.enabled }} 69 - port: {{ .Values.agones.allocator.service.grpc.port }} 70 name: {{ .Values.agones.allocator.service.grpc.portName }} 71 targetPort: {{ .Values.agones.allocator.service.grpc.targetPort }} 72 {{- if .Values.agones.allocator.service.grpc.appProtocol }} 73 appProtocol: {{.Values.agones.allocator.service.grpc.appProtocol}} 74 {{- end}} 75 {{- if eq .Values.agones.allocator.service.serviceType "NodePort" }} 76 nodePort: {{ .Values.agones.allocator.service.grpc.nodePort }} 77 {{- end }} 78 protocol: TCP 79 {{- end }} 80 type: {{ .Values.agones.allocator.service.serviceType }} 81 {{- if (ne .Values.agones.allocator.service.clusterIP "") }} 82 clusterIP: {{ .Values.agones.allocator.service.clusterIP }} 83 {{- end }} 84 {{- if $useLoadBalancerIP }} 85 loadBalancerIP: {{ .Values.agones.allocator.service.loadBalancerIP }} 86 {{- end }} 87 {{- if eq .Values.agones.allocator.service.serviceType "LoadBalancer" }} 88 externalTrafficPolicy: {{ .Values.agones.allocator.service.externalTrafficPolicy }} 89 {{- if .Values.agones.allocator.service.loadBalancerSourceRanges }} 90 loadBalancerSourceRanges: 91 {{ toYaml .Values.agones.allocator.service.loadBalancerSourceRanges | indent 4 }} 92 {{- end }} 93 {{- end }} 94 --- 95 apiVersion: v1 96 kind: Service 97 metadata: 98 name: {{ .Values.agones.allocator.serviceMetrics.name }} 99 namespace: {{ .Release.Namespace }} 100 labels: 101 multicluster.agones.dev/role: allocator 102 app: {{ template "agones.name" . }} 103 chart: {{ template "agones.chart" . }} 104 release: {{ .Release.Name }} 105 heritage: {{ .Release.Service }} 106 {{- if .Values.agones.allocator.serviceMetrics.annotations }} 107 annotations: 108 {{ toYaml .Values.agones.allocator.serviceMetrics.annotations | indent 4 }} 109 {{- end }} 110 spec: 111 selector: 112 multicluster.agones.dev/role: allocator 113 ports: 114 - port: {{ .Values.agones.allocator.serviceMetrics.http.port }} 115 name: {{ .Values.agones.allocator.serviceMetrics.http.portName }} 116 targetPort: 8080 117 protocol: TCP 118 {{- if and (.Values.agones.metrics.prometheusEnabled) (.Values.agones.metrics.serviceMonitor.enabled) }} 119 --- 120 apiVersion: monitoring.coreos.com/v1 121 kind: ServiceMonitor 122 metadata: 123 name: agones-allocator-monitor 124 namespace: {{ .Release.Namespace }} 125 labels: 126 multicluster.agones.dev/role: allocator 127 app: {{ template "agones.name" . }} 128 chart: {{ template "agones.chart" . }} 129 release: {{ .Release.Name }} 130 heritage: {{ .Release.Service }} 131 spec: 132 selector: 133 matchLabels: 134 multicluster.agones.dev/role: allocator 135 endpoints: 136 - port: {{ .Values.agones.allocator.serviceMetrics.http.portName }} 137 path: /metrics 138 interval: {{ .Values.agones.metrics.serviceMonitor.interval }} 139 {{- end }} 140 --- 141 # Deploy pods to run the agones-allocator code 142 apiVersion: apps/v1 143 kind: Deployment 144 metadata: 145 name: agones-allocator 146 namespace: {{ .Release.Namespace }} 147 labels: 148 multicluster.agones.dev/role: allocator 149 app: {{ template "agones.name" . }} 150 release: {{ .Release.Name }} 151 heritage: {{ .Release.Service }} 152 spec: 153 replicas: {{ .Values.agones.allocator.replicas }} 154 {{- if .Values.agones.allocator.updateStrategy }} 155 strategy: 156 {{- toYaml .Values.agones.allocator.updateStrategy | nindent 4}} 157 {{- end }} 158 selector: 159 matchLabels: 160 multicluster.agones.dev/role: allocator 161 app: {{ template "agones.name" . }} 162 release: {{ .Release.Name }} 163 heritage: {{ .Release.Service }} 164 template: 165 metadata: 166 labels: 167 multicluster.agones.dev/role: allocator 168 app: {{ template "agones.name" . }} 169 release: {{ .Release.Name }} 170 heritage: {{ .Release.Service }} 171 {{- if .Values.agones.allocator.labels }} 172 {{- toYaml .Values.agones.allocator.labels | nindent 8 }} 173 {{- end }} 174 annotations: 175 {{- if .Values.agones.allocator.generateTLS }} 176 revision/tls-cert: {{ .Release.Revision | quote }} 177 {{- end }} 178 {{- if and (.Values.agones.metrics.prometheusServiceDiscovery) (.Values.agones.metrics.prometheusEnabled) }} 179 prometheus.io/scrape: "true" 180 prometheus.io/port: "8080" 181 prometheus.io/path: "/metrics" 182 {{- end }} 183 {{- if .Values.agones.allocator.annotations }} 184 {{- toYaml .Values.agones.allocator.annotations | nindent 8 }} 185 {{- end }} 186 spec: 187 {{- if .Values.agones.allocator.topologySpreadConstraints }} 188 topologySpreadConstraints: 189 {{- toYaml .Values.agones.allocator.topologySpreadConstraints | nindent 8 }} 190 {{- end }} 191 affinity: 192 {{- if .Values.agones.allocator.affinity }} 193 {{- if .Values.agones.requireDedicatedNodes }} 194 {{- fail "agones.allocator.affinity and agones.requireDedicatedNodes cannot be set at the same time!" }} 195 {{- end}} 196 {{- end}} 197 {{- if .Values.agones.allocator.affinity }} 198 {{ toYaml .Values.agones.allocator.affinity | indent 8 }} 199 {{- else}} 200 nodeAffinity: 201 {{- if .Values.agones.requireDedicatedNodes }} 202 requiredDuringSchedulingIgnoredDuringExecution: 203 nodeSelectorTerms: 204 - matchExpressions: 205 {{- else}} 206 preferredDuringSchedulingIgnoredDuringExecution: 207 - weight: 1 208 preference: 209 matchExpressions: 210 {{- end }} 211 - key: agones.dev/agones-system 212 operator: Exists 213 {{- end }} 214 {{- if .Values.agones.allocator.nodeSelector }} 215 nodeSelector: 216 {{ toYaml .Values.agones.allocator.nodeSelector | indent 8 }} 217 {{- end }} 218 {{- if .Values.agones.allocator.tolerations }} 219 tolerations: 220 {{ toYaml .Values.agones.allocator.tolerations | indent 8 }} 221 {{- end }} 222 serviceAccountName: {{ $.Values.agones.serviceaccount.allocator.name }} 223 terminationGracePeriodSeconds: {{ mul .Values.agones.allocator.readiness.periodSeconds .Values.agones.allocator.readiness.failureThreshold 3 }} 224 {{- if eq .Values.agones.allocator.disableTLS false }} 225 volumes: 226 - name: tls 227 secret: 228 secretName: allocator-tls 229 {{- if eq .Values.agones.allocator.disableMTLS false }} 230 - name: client-ca 231 secret: 232 secretName: allocator-client-ca 233 {{- end }} 234 {{- end }} 235 containers: 236 - name: agones-allocator 237 image: "{{ .Values.agones.image.registry }}/{{ .Values.agones.image.allocator.name}}:{{ default .Values.agones.image.tag .Values.agones.image.allocator.tag }}" 238 imagePullPolicy: {{ .Values.agones.image.allocator.pullPolicy }} 239 securityContext: 240 runAsNonRoot: true 241 runAsUser: 1000 242 allowPrivilegeEscalation: false 243 livenessProbe: 244 httpGet: 245 path: /live 246 port: 8080 247 initialDelaySeconds: {{ .Values.agones.allocator.healthCheck.initialDelaySeconds }} 248 periodSeconds: {{ .Values.agones.allocator.healthCheck.periodSeconds }} 249 failureThreshold: {{ .Values.agones.allocator.healthCheck.failureThreshold }} 250 timeoutSeconds: {{ .Values.agones.allocator.healthCheck.timeoutSeconds }} 251 readinessProbe: 252 httpGet: 253 path: /ready 254 port: 8080 255 initialDelaySeconds: {{ .Values.agones.allocator.readiness.initialDelaySeconds }} 256 periodSeconds: {{ .Values.agones.allocator.readiness.periodSeconds }} 257 failureThreshold: {{ .Values.agones.allocator.readiness.failureThreshold }} 258 env: 259 {{- if .Values.agones.allocator.service.http.enabled }} 260 - name: HTTP_PORT 261 value: {{ .Values.agones.allocator.service.http.targetPort | quote }} 262 {{- end }} 263 {{- if .Values.agones.allocator.service.grpc.enabled }} 264 - name: GRPC_PORT 265 value: {{ .Values.agones.allocator.service.grpc.targetPort | quote }} 266 {{- end }} 267 - name: HTTP_UNALLOCATED_STATUS_CODE 268 value: {{ .Values.agones.allocator.service.http.unallocatedStatusCode | quote }} 269 - name: API_SERVER_QPS 270 value: {{ .Values.agones.allocator.apiServerQPS | quote }} 271 - name: API_SERVER_QPS_BURST 272 value: {{ .Values.agones.allocator.apiServerQPSBurst | quote }} 273 - name: PROMETHEUS_EXPORTER 274 value: {{ .Values.agones.metrics.prometheusEnabled | quote }} 275 - name: STACKDRIVER_EXPORTER 276 value: {{ .Values.agones.metrics.stackdriverEnabled | quote }} 277 - name: GCP_PROJECT_ID 278 value: {{ .Values.agones.metrics.stackdriverProjectID | quote }} 279 - name: STACKDRIVER_LABELS 280 value: {{ .Values.agones.metrics.stackdriverLabels | quote }} 281 - name: DISABLE_MTLS 282 value: {{ .Values.agones.allocator.disableMTLS | quote }} 283 - name: DISABLE_TLS 284 value: {{ .Values.agones.allocator.disableTLS | quote }} 285 - name: REMOTE_ALLOCATION_TIMEOUT 286 value: {{ .Values.agones.allocator.remoteAllocationTimeout | quote }} 287 - name: TOTAL_REMOTE_ALLOCATION_TIMEOUT 288 value: {{ .Values.agones.allocator.totalRemoteAllocationTimeout | quote }} 289 - name: POD_NAME 290 valueFrom: 291 fieldRef: 292 fieldPath: metadata.name 293 - name: POD_NAMESPACE 294 valueFrom: 295 fieldRef: 296 fieldPath: metadata.namespace 297 - name: CONTAINER_NAME 298 value: "agones-allocator" 299 - name: LOG_LEVEL 300 value: {{ .Values.agones.allocator.logLevel | quote }} 301 - name: FEATURE_GATES 302 value: {{ .Values.agones.featureGates | quote }} 303 - name: ALLOCATION_BATCH_WAIT_TIME 304 value: {{ .Values.agones.allocator.allocationBatchWaitTime | quote }} 305 - name: READINESS_SHUTDOWN_DURATION 306 value: {{ mul .Values.agones.allocator.readiness.periodSeconds .Values.agones.extensions.readiness.failureThreshold 2 }}s 307 {{- $featureGates := include "agones.featureGates" . | fromYaml }} 308 {{- if $featureGates.ProcessorAllocator }} 309 - name: PROCESSOR_MAX_BATCH_SIZE 310 value: {{ .Values.agones.allocator.processor.maxBatchSize | quote }} 311 - name: PROCESSOR_GRPC_ADDRESS 312 value: {{ .Values.agones.allocator.processor.grpc.address | quote }} 313 - name: PROCESSOR_GRPC_PORT 314 value: {{ .Values.agones.allocator.processor.grpc.port | quote }} 315 {{- end }} 316 ports: 317 {{- if .Values.agones.allocator.service.http.enabled }} 318 - name: {{ .Values.agones.allocator.service.http.portName }} 319 containerPort: {{ .Values.agones.allocator.service.http.targetPort }} 320 {{- if .Values.agones.allocator.service.grpc.enabled }} 321 {{- if ne .Values.agones.allocator.service.grpc.port .Values.agones.allocator.service.http.port }} 322 - name: {{ .Values.agones.allocator.service.grpc.portName }} 323 containerPort: {{ .Values.agones.allocator.service.grpc.targetPort }} 324 {{- end }} 325 {{- end }} 326 {{- else if .Values.agones.allocator.service.grpc.enabled }} 327 - name: {{ .Values.agones.allocator.service.grpc.portName }} 328 containerPort: {{ .Values.agones.allocator.service.grpc.targetPort }} 329 {{- end }} 330 - name: {{ .Values.agones.allocator.serviceMetrics.http.portName }} 331 containerPort: {{ .Values.agones.allocator.serviceMetrics.http.port }} 332 {{- if eq .Values.agones.allocator.disableTLS false }} 333 volumeMounts: 334 - mountPath: /home/allocator/tls 335 name: tls 336 readOnly: true 337 {{- if eq .Values.agones.allocator.disableMTLS false }} 338 - mountPath: /home/allocator/client-ca 339 name: client-ca 340 readOnly: true 341 {{- end }} 342 {{- end }} 343 {{- if .Values.agones.allocator.resources }} 344 resources: 345 {{ toYaml .Values.agones.allocator.resources | indent 10 }} 346 {{- end }} 347 {{- if .Values.agones.image.controller.pullSecret }} 348 imagePullSecrets: 349 - name: {{.Values.agones.image.controller.pullSecret}} 350 {{- end }} 351 {{- if .Values.agones.allocator.pdb.enabled }} 352 --- 353 apiVersion: policy/v1 354 kind: PodDisruptionBudget 355 metadata: 356 name: agones-allocator-pdb 357 spec: 358 {{- if .Values.agones.allocator.pdb.minAvailable }} 359 {{- if .Values.agones.allocator.pdb.maxUnavailable }} 360 {{- fail "minAvailable and maxUnavailable are mutually exclusive!" }} 361 {{- end}} 362 {{- end}} 363 minAvailable: {{ .Values.agones.allocator.pdb.minAvailable }} 364 maxUnavailable: {{ .Values.agones.allocator.pdb.maxUnavailable }} 365 selector: 366 matchLabels: 367 multicluster.agones.dev/role: allocator 368 app: {{ template "agones.name" . }} 369 release: {{ .Release.Name }} 370 heritage: {{ .Release.Service }} 371 {{- end }} 372 --- 373 # Create a ClusterRole in that grants access to the agones allocation api 374 apiVersion: rbac.authorization.k8s.io/v1 375 kind: ClusterRole 376 metadata: 377 name: agones-allocator 378 labels: 379 app: {{ template "agones.name" $ }} 380 chart: {{ template "agones.chart" $ }} 381 release: {{ $.Release.Name }} 382 heritage: {{ $.Release.Service }} 383 rules: 384 - apiGroups: [""] 385 resources: ["events"] 386 verbs: ["create", "patch"] 387 - apiGroups: ["allocation.agones.dev"] 388 resources: ["gameserverallocations"] 389 verbs: ["create"] 390 - apiGroups: [""] 391 resources: ["nodes", "secrets"] 392 verbs: ["get", "list", "watch"] 393 - apiGroups: ["agones.dev"] 394 resources: ["gameservers", "gameserversets"] 395 verbs: ["get", "list", "update", "watch"] 396 - apiGroups: ["agones.dev"] 397 resources: ["gameservers"] 398 verbs: ["patch"] 399 - apiGroups: ["multicluster.agones.dev"] 400 resources: ["gameserverallocationpolicies"] 401 verbs: ["get", "list", "watch"] 402 403 --- 404 # Create a ServiceAccount that will be bound to the above role 405 apiVersion: v1 406 kind: ServiceAccount 407 metadata: 408 name: agones-allocator 409 namespace: {{ .Release.Namespace }} 410 labels: 411 app: {{ template "agones.name" $ }} 412 chart: {{ template "agones.chart" $ }} 413 release: {{ $.Release.Name }} 414 heritage: {{ $.Release.Service }} 415 {{- if .Values.agones.serviceaccount.allocator.annotations }} 416 annotations: 417 {{- toYaml .Values.agones.serviceaccount.allocator.annotations | nindent 4 }} 418 {{- end }} 419 {{- if .Values.agones.serviceaccount.allocator.labels }} 420 labels: 421 {{- toYaml .Values.agones.serviceaccount.allocator.labels | nindent 4 }} 422 {{- end }} 423 --- 424 # Bind the agones-allocator ServiceAccount to the agones-allocator ClusterRole 425 apiVersion: rbac.authorization.k8s.io/v1 426 kind: ClusterRoleBinding 427 metadata: 428 name: agones-allocator 429 labels: 430 app: {{ template "agones.name" $ }} 431 chart: {{ template "agones.chart" $ }} 432 release: {{ $.Release.Name }} 433 heritage: {{ $.Release.Service }} 434 subjects: 435 - kind: ServiceAccount 436 name: {{ $.Values.agones.serviceaccount.allocator.name }} 437 namespace: {{ .Release.Namespace }} 438 roleRef: 439 apiGroup: rbac.authorization.k8s.io 440 kind: ClusterRole 441 name: agones-allocator 442 443 {{- end }} 444 445 {{- if not .Values.agones.allocator.disableSecretCreation }} 446 --- 447 # Allocation CA 448 {{- $selfSigned := genSelfSignedCert "" nil nil 3650 }} 449 {{- $ca := genCA "allocation-ca" 3650 }} 450 apiVersion: v1 451 kind: Secret 452 metadata: 453 name: allocator-client-ca 454 namespace: {{ .Release.Namespace }} 455 labels: 456 app: {{ template "agones.name" . }} 457 chart: "{{ .Chart.Name }}-{{ .Chart.Version }}" 458 release: "{{ .Release.Name }}" 459 heritage: "{{ .Release.Service }}" 460 data: 461 {{- if .Values.agones.allocator.generateClientTLS }} 462 allocator-client.default.crt: {{ b64enc $selfSigned.Cert }} 463 {{- end }} 464 {{- if .Values.agones.allocator.generateTLS }} 465 client-ca.crt: {{ b64enc $ca.Cert }} 466 {{- else if .Values.agones.allocator.clientCAs }} 467 {{- range $caField, $caContent := .Values.agones.allocator.clientCAs }} 468 {{ $caField }}: {{ b64enc $caContent }} 469 {{- end }} 470 {{- else }} 471 {{- (.Files.Glob "certs/allocator/client-ca/*").AsSecrets | nindent 2 }} 472 {{- end }} 473 474 --- 475 # Allocation TLS certs 476 {{- $cert := genSignedCert "" ($useLoadBalancerIP | ternary (list .Values.agones.allocator.service.loadBalancerIP) nil) nil 3650 $ca }} 477 apiVersion: v1 478 kind: Secret 479 type: kubernetes.io/tls 480 metadata: 481 name: allocator-tls 482 namespace: {{ .Release.Namespace }} 483 labels: 484 app: {{ template "agones.name" . }} 485 chart: "{{ .Chart.Name }}-{{ .Chart.Version }}" 486 release: "{{ .Release.Name }}" 487 heritage: "{{ .Release.Service }}" 488 data: 489 {{- if .Values.agones.allocator.generateTLS }} 490 tls.crt: {{ b64enc $cert.Cert }} 491 tls.key: {{ b64enc $cert.Key }} 492 {{- else }} 493 tls.crt: {{ default (.Files.Get "certs/allocator/server.crt") .Values.agones.allocator.tlsCert | b64enc }} 494 tls.key: {{ default (.Files.Get "certs/allocator/server.key") .Values.agones.allocator.tlsKey | b64enc }} 495 {{- end }} 496 497 --- 498 # Allocation TLS CA 499 apiVersion: v1 500 kind: Secret 501 metadata: 502 name: allocator-tls-ca 503 namespace: {{ .Release.Namespace }} 504 labels: 505 app: {{ template "agones.name" . }} 506 chart: "{{ .Chart.Name }}-{{ .Chart.Version }}" 507 release: "{{ .Release.Name }}" 508 heritage: "{{ .Release.Service }}" 509 data: 510 {{- if .Values.agones.allocator.generateTLS }} 511 tls-ca.crt: {{ b64enc $ca.Cert }} 512 {{- else }} 513 tls-ca.crt: {{ default (.Files.Get "certs/allocator/server.crt") .Values.agones.allocator.tlsCert | b64enc }} 514 {{- end }} 515 516 # Default allocation client secret 517 {{- if .Values.agones.allocator.generateClientTLS }} 518 {{- range .Values.gameservers.namespaces }} 519 --- 520 apiVersion: v1 521 kind: Secret 522 type: kubernetes.io/tls 523 metadata: 524 name: allocator-client.default 525 namespace: {{ . }} 526 labels: 527 app: {{ template "agones.name" $ }} 528 chart: "{{ $.Chart.Name }}-{{ $.Chart.Version }}" 529 release: "{{ $.Release.Name }}" 530 heritage: "{{ $.Release.Service }}" 531 data: 532 tls.crt: {{ b64enc $selfSigned.Cert }} 533 tls.key: {{ b64enc $selfSigned.Key }} 534 {{- end }} 535 {{- end }} 536 {{- end }}