From fcc84ff0771d44bc523a459a8165778f50b08c9c Mon Sep 17 00:00:00 2001 From: Ciara Stacke Date: Thu, 24 Aug 2023 14:51:13 +0100 Subject: [PATCH 1/5] Integrate prometheus exporter and enable metrics server --- Makefile | 2 +- cmd/gateway/commands.go | 35 ++++++++++ cmd/gateway/validation.go | 8 +++ cmd/gateway/validation_test.go | 37 +++++++++++ deploy/helm-chart/README.md | 3 + deploy/helm-chart/templates/deployment.yaml | 20 ++++++ deploy/helm-chart/values.yaml | 8 +++ docs/cli-help.md | 4 +- docs/monitoring.md | 64 +++++++++++++++++++ go.mod | 4 +- go.sum | 4 ++ internal/mode/static/config/config.go | 11 ++++ internal/mode/static/manager.go | 52 ++++++++++++--- internal/mode/static/metrics/nginx.go | 37 +++++++++++ internal/mode/static/nginx/conf/nginx.conf | 9 +++ .../mode/static/state/change_processor.go | 7 +- internal/mode/static/state/graph/gateway.go | 3 +- .../static/state/graph/gateway_listener.go | 25 ++++++-- .../mode/static/state/graph/gateway_test.go | 25 +++++++- internal/mode/static/state/graph/graph.go | 3 +- .../mode/static/state/graph/graph_test.go | 5 ++ 21 files changed, 342 insertions(+), 24 deletions(-) create mode 100644 docs/monitoring.md create mode 100644 internal/mode/static/metrics/nginx.go diff --git a/Makefile b/Makefile index eeb61356e1..670c7b3427 100644 --- a/Makefile +++ b/Makefile @@ -135,7 +135,7 @@ build-nkg-debug-image: debug-build build-nkg-image ## Build NKG image with debug generate-manifests: ## Generate manifests using Helm. cp $(CHART_DIR)/crds/* $(MANIFEST_DIR)/crds/ helm template nginx-gateway $(CHART_DIR) $(HELM_TEMPLATE_COMMON_ARGS) $(HELM_TEMPLATE_EXTRA_ARGS_FOR_ALL_MANIFESTS_FILE) -n nginx-gateway | cat $(strip $(MANIFEST_DIR))/namespace.yaml - > $(strip $(MANIFEST_DIR))/nginx-gateway.yaml - helm template nginx-gateway $(CHART_DIR) $(HELM_TEMPLATE_COMMON_ARGS) -n nginx-gateway -s templates/deployment.yaml > conformance/provisioner/static-deployment.yaml + helm template nginx-gateway $(CHART_DIR) $(HELM_TEMPLATE_COMMON_ARGS) --set metrics.enable=false -n nginx-gateway -s templates/deployment.yaml > conformance/provisioner/static-deployment.yaml helm template nginx-gateway $(CHART_DIR) $(HELM_TEMPLATE_COMMON_ARGS) -n nginx-gateway -s templates/service.yaml > $(strip $(MANIFEST_DIR))/service/loadbalancer.yaml helm template nginx-gateway $(CHART_DIR) $(HELM_TEMPLATE_COMMON_ARGS) --set service.annotations.'service\.beta\.kubernetes\.io\/aws-load-balancer-type'="nlb" -n nginx-gateway -s templates/service.yaml > $(strip $(MANIFEST_DIR))/service/loadbalancer-aws-nlb.yaml helm template nginx-gateway $(CHART_DIR) $(HELM_TEMPLATE_COMMON_ARGS) --set service.type=NodePort --set service.externalTrafficPolicy="" -n nginx-gateway -s templates/service.yaml > $(strip $(MANIFEST_DIR))/service/nodeport.yaml diff --git a/cmd/gateway/commands.go b/cmd/gateway/commands.go index 7627ee5fdc..134e353cb3 100644 --- a/cmd/gateway/commands.go +++ b/cmd/gateway/commands.go @@ -123,6 +123,9 @@ func createStaticModeCommand() *cobra.Command { configName := stringValidatingValue{ validator: validateResourceName, } + var enableMetrics bool + var metricsListenPort int + var metricsSecure bool cmd := &cobra.Command{ Use: "static-mode", @@ -153,6 +156,16 @@ func createStaticModeCommand() *cobra.Command { gwNsName = &gateway.value } + metricsConfig := config.MetricsConfig{} + if enableMetrics { + if err := validatePort(metricsListenPort); err != nil { + return fmt.Errorf("error validating metrics listen port: %w", err) + } + metricsConfig.MetricsEnabled = enableMetrics + metricsConfig.MetricsPort = metricsListenPort + metricsConfig.Secure = metricsSecure + } + conf := config.Config{ GatewayCtlrName: gatewayCtlrName.value, ConfigName: configName.String(), @@ -163,6 +176,7 @@ func createStaticModeCommand() *cobra.Command { Namespace: namespace, GatewayNsName: gwNsName, UpdateGatewayClassStatus: updateGCStatus, + MetricsConfig: metricsConfig, } if err := static.StartManager(conf); err != nil { @@ -198,6 +212,27 @@ func createStaticModeCommand() *cobra.Command { "Update the status of the GatewayClass resource.", ) + cmd.Flags().BoolVar( + &enableMetrics, + "enable-metrics", + false, + "Enable exposing metrics in the Prometheus format.", + ) + + cmd.Flags().IntVar( + &metricsListenPort, + "metrics-listen-port", + 9113, + "Set the port where the metrics are exposed. [1023 - 65535]", + ) + + cmd.Flags().BoolVar( + &metricsSecure, + "metrics-secure-serving", + false, + "Enables serving metrics via https. By default metrics are served via http.", + ) + return cmd } diff --git a/cmd/gateway/validation.go b/cmd/gateway/validation.go index a92dd76018..8a40d7970f 100644 --- a/cmd/gateway/validation.go +++ b/cmd/gateway/validation.go @@ -99,3 +99,11 @@ func validateIP(ip string) error { return nil } + +// validatePort makes sure a given port is inside the valid port range for its usage +func validatePort(port int) error { + if port < 1024 || port > 65535 { + return fmt.Errorf("port outside of valid port range [1024 - 65535]: %v", port) + } + return nil +} diff --git a/cmd/gateway/validation_test.go b/cmd/gateway/validation_test.go index 47231c73ec..66a983a3d7 100644 --- a/cmd/gateway/validation_test.go +++ b/cmd/gateway/validation_test.go @@ -294,3 +294,40 @@ func TestValidateIP(t *testing.T) { }) } } + +func TestValidatePort(t *testing.T) { + tests := []struct { + name string + port int + expErr bool + }{ + { + name: "port under minimum allowed value", + port: 1023, + expErr: true, + }, + { + name: "port over maximum allowed value", + port: 65536, + expErr: true, + }, + { + name: "valid port", + port: 9113, + expErr: false, + }, + } + + for _, tc := range tests { + t.Run(tc.name, func(t *testing.T) { + g := NewGomegaWithT(t) + + err := validatePort(tc.port) + if !tc.expErr { + g.Expect(err).ToNot(HaveOccurred()) + } else { + g.Expect(err).To(HaveOccurred()) + } + }) + } +} diff --git a/deploy/helm-chart/README.md b/deploy/helm-chart/README.md index 3d4dddc08e..fa1e95ef15 100644 --- a/deploy/helm-chart/README.md +++ b/deploy/helm-chart/README.md @@ -142,3 +142,6 @@ The following tables lists the configurable parameters of the NGINX Kubernetes G | `service.externalTrafficPolicy` | The `externalTrafficPolicy` of the service. The value `Local` preserves the client source IP. | Local | | `service.annotations` | The `annotations` of the NGINX Kubernetes Gateway service. | {} | | `service.ports` | A list of ports to expose through the NGINX Kubernetes Gateway service. Update it to match the listener ports from your Gateway resource. Follows the conventional Kubernetes yaml syntax for service ports. | [ port: 80, targetPort: 80, protocol: TCP, name: http; port: 443, targetPort: 443, protocol: TCP, name: https ] | +| `metrics.enable` | Enable exposing metrics in the Prometheus format. |false | +| `metrics.port` | Sets the port where the Prometheus metrics are exposed. Format: [1024 - 65535] |9113 | +| `metrics.secure` | Configures if the metrics endpoint should be secured using https. Please note that this endpoint will be secured with a self-signed certificate. |false | diff --git a/deploy/helm-chart/templates/deployment.yaml b/deploy/helm-chart/templates/deployment.yaml index d662174283..a072f37103 100644 --- a/deploy/helm-chart/templates/deployment.yaml +++ b/deploy/helm-chart/templates/deployment.yaml @@ -16,6 +16,14 @@ spec: metadata: labels: {{- include "nginx-gateway.selectorLabels" . | nindent 8 }} + {{- if .Values.metrics.enable }} + annotations: + prometheus.io/scrape: "true" + prometheus.io/port: "{{ .Values.metrics.port }}" + {{- if .Values.metrics.secure }} + prometheus.io/scheme: "https" + {{- end }} + {{- end }} spec: containers: - args: @@ -23,6 +31,13 @@ spec: - --gateway-ctlr-name={{ .Values.nginxGateway.gatewayControllerName }} - --gatewayclass={{ .Values.nginxGateway.gatewayClassName }} - --config={{ include "nginx-gateway.config-name" . }} + {{- if .Values.metrics.enable }} + - --enable-metrics=true + - --metrics-listen-port={{ .Values.metrics.port }} + {{- if .Values.metrics.secure }} + - --metrics-secure-serving=true + {{- end }} + {{- end }} env: - name: POD_IP valueFrom: @@ -35,6 +50,11 @@ spec: image: {{ .Values.nginxGateway.image.repository }}:{{ .Values.nginxGateway.image.tag | default .Chart.AppVersion }} imagePullPolicy: {{ .Values.nginxGateway.image.pullPolicy }} name: nginx-gateway + {{- if .Values.metrics.enable }} + ports: + - name: prometheus + containerPort: {{ .Values.metrics.port }} + {{- end }} securityContext: allowPrivilegeEscalation: false capabilities: diff --git a/deploy/helm-chart/values.yaml b/deploy/helm-chart/values.yaml index d616a630cb..be198935fa 100644 --- a/deploy/helm-chart/values.yaml +++ b/deploy/helm-chart/values.yaml @@ -54,3 +54,11 @@ service: targetPort: 443 protocol: TCP name: https + +metrics: + ## Expose metrics in the Prometheus format. + enable: false + ## Configures the port to scrape the metrics. + port: 9113 + ## Configures if the metrics endpoint should be secured using https. + secure: false diff --git a/docs/cli-help.md b/docs/cli-help.md index df780388d6..227e0ba8be 100644 --- a/docs/cli-help.md +++ b/docs/cli-help.md @@ -20,4 +20,6 @@ Flags: | `gatewayclass` | `string` | The name of the GatewayClass resource. Every NGINX Gateway must have a unique corresponding GatewayClass resource. | | `gateway` | `string` | The namespaced name of the Gateway resource to use. Must be of the form: `NAMESPACE/NAME`. If not specified, the control plane will process all Gateways for the configured GatewayClass. However, among them, it will choose the oldest resource by creation timestamp. If the timestamps are equal, it will choose the resource that appears first in alphabetical order by {namespace}/{name}. | | `config` | `string` | The name of the NginxGateway resource to be used for this controller's dynamic configuration. Lives in the same Namespace as the controller. | -| `update-gatewayclass-status` | `bool` | Update the status of the GatewayClass resource. (default true) | +| `enable-metrics` | `bool` | Enable metrics reporting in the Prometheus format. (default false) | +| `metrics-listen-port` | `int` | Sets the port where the Prometheus metrics are exposed. Format: `[1024 - 65535]` (default `9113`) | +| `metrics-secure-serving` | `bool` | Configures if the metrics endpoint should be secured using https. Please note that this endpoint will be secured with a self-signed certificate. (default false) | diff --git a/docs/monitoring.md b/docs/monitoring.md new file mode 100644 index 0000000000..0ac600d0ce --- /dev/null +++ b/docs/monitoring.md @@ -0,0 +1,64 @@ +# Monitoring + +The NGINX Kubernetes Gateway exposes a number of metrics in the [Prometheus](https://prometheus.io/) format. Those +include NGINX and the controller-runtime metrics. These are delivered using a metrics server orchestrated by the +controller-runtime package. + +## Enabling Metrics + +### Using Helm + +If you're using *Helm* to install the NGINX Kubernetes Gateway, to enable Prometheus metrics, configure the `metrics.*` +parameters of the Helm chart. See the [Helm README](/deploy/helm-chart/README.md). Please note that if `metrics.secure` +is set to true, as the metrics server is using a self-signed certificate, the Prometheus pod scrape configuration will +also require the `insecure_skip_verify` flag set. See [the Prometheus documentation](https://prometheus.io/docs/prometheus/latest/configuration/configuration/#tls_config). + +### Using Manifests + +If you're using *Kubernetes manifests* to install the NGINX Kubernetes Gateway, modify the [manifest](/deploy/manifests/nginx-gateway.yaml) +to enable Prometheus metrics to enable the following: + +1. Run the NGINX Kubernetes Gateway with the `-enable-metrics` [command-line argument](/docs/cli-help.md). + As a result, the NGINX Kubernetes Gateway will expose NGINX metrics in the Prometheus format via the path `/metrics` + on port `9113` (customizable via the `-metrics-listen-port` [command-line argument](/docs/cli-help.md)) using http + (customizable via the `-metrics-secure-serving` [command-line argument](/docs/cli-help.md)). +2. Add the Prometheus port to the list of the ports of the NGINX Kubernetes Gateway container in the template of the + NGINX Kubernetes Gateway pod: + + ```yaml + - name: prometheus + containerPort: 9113 + ``` + +3. Make Prometheus aware of the NGINX Kubernetes Gateway targets by adding the following annotations to the template of + the NGINX Kubernetes Gateway pod (note: this assumes your Prometheus is configured to discover targets by analyzing the + annotations of pods): + + ```yaml + annotations: + prometheus.io/scrape: "true" + prometheus.io/port: "9113" + ``` + + If the `-metrics-secure-serving` flag is enabled, the following annotation will also needed to be added to the pod spec: + + ```yaml + prometheus.io/scheme: "https" + ``` + + As the metrics server is using a self-signed certificate, the Prometheus pod scrape configuration will also require the + `insecure_skip_verify` flag set. See [the Prometheus documentation](https://prometheus.io/docs/prometheus/latest/configuration/configuration/#tls_config) + +## Available Metrics + +The NGINX Kubernetes Gateway exports the following metrics: + +- NGINX metrics: + - Exported by NGINX. Refer to the [NGINX Prometheus Exporter developer docs](https://github.com/nginxinc/nginx-prometheus-exporter#metrics-for-nginx-oss) + +- [controller-runtime](https://github.com/kubernetes-sigs/controller-runtime) metrics. These include: + - Total number of reconcilation errors per controller + - Length of reconcile queue per controller + - Reconcilation latency + - Usual resource metrics such as CPU, memory usage, file descriptor usage + - Go runtime metrics such as number of Go routines, GC duration, and Go version information diff --git a/go.mod b/go.mod index 46c6bd6220..42510c6e6f 100644 --- a/go.mod +++ b/go.mod @@ -9,8 +9,10 @@ require ( github.com/go-logr/logr v1.2.4 github.com/google/go-cmp v0.5.9 github.com/maxbrunsfeld/counterfeiter/v6 v6.7.0 + github.com/nginxinc/nginx-prometheus-exporter v0.11.0 github.com/onsi/ginkgo/v2 v2.11.0 github.com/onsi/gomega v1.27.10 + github.com/prometheus/client_golang v1.16.0 github.com/spf13/cobra v1.7.0 go.uber.org/zap v1.25.0 k8s.io/api v0.28.1 @@ -55,9 +57,9 @@ require ( github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/reflect2 v1.0.2 // indirect github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect + github.com/nginxinc/nginx-plus-go-client v0.10.0 // indirect github.com/pkg/errors v0.9.1 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect - github.com/prometheus/client_golang v1.16.0 // indirect github.com/prometheus/client_model v0.4.0 // indirect github.com/prometheus/common v0.44.0 // indirect github.com/prometheus/procfs v0.10.1 // indirect diff --git a/go.sum b/go.sum index ec9d7db72f..aab3b8f0ac 100644 --- a/go.sum +++ b/go.sum @@ -127,6 +127,10 @@ github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9G github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= +github.com/nginxinc/nginx-plus-go-client v0.10.0 h1:3zsMMkPvRDo8D7ZSprXtbAEW/SDmezZWzxdyS+6oAlc= +github.com/nginxinc/nginx-plus-go-client v0.10.0/go.mod h1:0v3RsQCvRn/IyrMtW+DK6CNkz+PxEsXDJPjQ3yUMBF0= +github.com/nginxinc/nginx-prometheus-exporter v0.11.0 h1:21xjnqNgxtni2jDgAQ90bl15uDnrTreO9sIlu1YsX/U= +github.com/nginxinc/nginx-prometheus-exporter v0.11.0/go.mod h1:GdyHnWAb8q8OW1Pssrrqbcqra0SH0Vn6UXICMmyWkw8= github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE= github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE= diff --git a/internal/mode/static/config/config.go b/internal/mode/static/config/config.go index f29b45b1de..11c2bc8c92 100644 --- a/internal/mode/static/config/config.go +++ b/internal/mode/static/config/config.go @@ -26,4 +26,15 @@ type Config struct { Namespace string // UpdateGatewayClassStatus enables updating the status of the GatewayClass resource. UpdateGatewayClassStatus bool + // MetricsConfig specifies the metrics config. + MetricsConfig MetricsConfig +} + +type MetricsConfig struct { + // MetricsPort is the port the metrics should be exposed on. + MetricsPort int + // MetricsEnabled is the flag for toggling metrics on or off. + MetricsEnabled bool + // Secure is the flag for toggling the metrics endpoint to https. + Secure bool } diff --git a/internal/mode/static/manager.go b/internal/mode/static/manager.go index f2754df8fe..26ed9f4750 100644 --- a/internal/mode/static/manager.go +++ b/internal/mode/static/manager.go @@ -16,6 +16,7 @@ import ( ctlr "sigs.k8s.io/controller-runtime" "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/manager" + "sigs.k8s.io/controller-runtime/pkg/metrics" metricsserver "sigs.k8s.io/controller-runtime/pkg/metrics/server" k8spredicate "sigs.k8s.io/controller-runtime/pkg/predicate" gatewayv1beta1 "sigs.k8s.io/gateway-api/apis/v1beta1" @@ -28,6 +29,7 @@ import ( "github.com/nginxinc/nginx-kubernetes-gateway/internal/framework/events" "github.com/nginxinc/nginx-kubernetes-gateway/internal/framework/status" "github.com/nginxinc/nginx-kubernetes-gateway/internal/mode/static/config" + nkgMetrics "github.com/nginxinc/nginx-kubernetes-gateway/internal/mode/static/metrics" ngxcfg "github.com/nginxinc/nginx-kubernetes-gateway/internal/mode/static/nginx/config" ngxvalidation "github.com/nginxinc/nginx-kubernetes-gateway/internal/mode/static/nginx/config/validation" "github.com/nginxinc/nginx-kubernetes-gateway/internal/mode/static/nginx/file" @@ -56,13 +58,9 @@ func StartManager(cfg config.Config) error { logger := cfg.Logger options := manager.Options{ - Scheme: scheme, - Logger: logger, - // We disable the metrics server because we reserve all ports (1-65535) for the data plane. - // Once we add support for Prometheus, we can make this port configurable by the user. - Metrics: metricsserver.Options{ - BindAddress: "0", - }, + Scheme: scheme, + Logger: logger, + Metrics: getMetricsConfig(cfg.MetricsConfig), } eventCh := make(chan interface{}) @@ -164,6 +162,11 @@ func StartManager(cfg config.Config) error { } } + // protectedPorts is the map of ports that may not be configured by a listener, and the name of what it is used for + protectedPorts := map[int32]string{ + int32(cfg.MetricsConfig.MetricsPort): "MetricsPort", + } + processor := state.NewChangeProcessorImpl(state.ChangeProcessorConfig{ GatewayCtlrName: cfg.GatewayCtlrName, GatewayClassName: cfg.GatewayClassName, @@ -172,8 +175,9 @@ func StartManager(cfg config.Config) error { Validators: validation.Validators{ HTTPFieldsValidator: ngxvalidation.HTTPValidator{}, }, - EventRecorder: recorder, - Scheme: scheme, + EventRecorder: recorder, + Scheme: scheme, + ProtectedPorts: protectedPorts, }) configGenerator := ngxcfg.NewGeneratorImpl() @@ -227,6 +231,13 @@ func StartManager(cfg config.Config) error { return fmt.Errorf("cannot register event loop: %w", err) } + if cfg.MetricsConfig.MetricsEnabled { + err = configureNginxMetrics(cfg.GatewayClassName) + if err != nil { + return fmt.Errorf("cannot register nginx metrics: %w", err) + } + } + logger.Info("Starting manager") return mgr.Start(ctx) } @@ -278,3 +289,26 @@ func setInitialConfig( // resource is processed by the controller return updateControlPlane(&config, logger, eventRecorder, configName, logLevelSetter) } + +func configureNginxMetrics(gatewayClassName string) error { + constLabels := map[string]string{"class": gatewayClassName} + ngxCollector, err := nkgMetrics.NewNginxMetricsClient(constLabels) + if err != nil { + return fmt.Errorf("cannot get NGINX metrics: %w", err) + } + metrics.Registry.MustRegister(ngxCollector) + return nil +} + +func getMetricsConfig(cfg config.MetricsConfig) metricsserver.Options { + metricsOptions := metricsserver.Options{BindAddress: "0"} + + if cfg.MetricsEnabled { + if cfg.Secure { + metricsOptions.SecureServing = true + } + metricsOptions.BindAddress = fmt.Sprintf(":%v", cfg.MetricsPort) + } + + return metricsOptions +} diff --git a/internal/mode/static/metrics/nginx.go b/internal/mode/static/metrics/nginx.go new file mode 100644 index 0000000000..30d371aeb3 --- /dev/null +++ b/internal/mode/static/metrics/nginx.go @@ -0,0 +1,37 @@ +package metrics + +import ( + "context" + "net" + "net/http" + + prometheusClient "github.com/nginxinc/nginx-prometheus-exporter/client" + nginxCollector "github.com/nginxinc/nginx-prometheus-exporter/collector" + "github.com/prometheus/client_golang/prometheus" +) + +const ( + nginxStatusSock = "/var/run/nginx/nginx-status.sock" + nginxStatusURI = "http://config-status/stub_status" +) + +// NewNginxMetricsClient creates an NginxClient to fetch stats from NGINX over a unix socket +func NewNginxMetricsClient(constLabels map[string]string) (prometheus.Collector, error) { + httpClient := getSocketClient(nginxStatusSock) + client, err := prometheusClient.NewNginxClient(&httpClient, nginxStatusURI) + if err != nil { + return nil, err + } + return nginxCollector.NewNginxCollector(client, "nginx_kubernetes_gateway", constLabels), nil +} + +// getSocketClient gets an http.Client with a unix socket transport. +func getSocketClient(sockPath string) http.Client { + return http.Client{ + Transport: &http.Transport{ + DialContext: func(_ context.Context, _, _ string) (net.Conn, error) { + return net.Dial("unix", sockPath) + }, + }, + } +} diff --git a/internal/mode/static/nginx/conf/nginx.conf b/internal/mode/static/nginx/conf/nginx.conf index 02f6c9f91f..74af2ee4db 100644 --- a/internal/mode/static/nginx/conf/nginx.conf +++ b/internal/mode/static/nginx/conf/nginx.conf @@ -14,4 +14,13 @@ http { server_names_hash_max_size 1024; variables_hash_bucket_size 512; variables_hash_max_size 1024; + + server { + listen unix:/var/run/nginx/nginx-status.sock; + access_log off; + + location /stub_status { + stub_status; + } + } } diff --git a/internal/mode/static/state/change_processor.go b/internal/mode/static/state/change_processor.go index bc6aa71da7..743cb6214c 100644 --- a/internal/mode/static/state/change_processor.go +++ b/internal/mode/static/state/change_processor.go @@ -55,12 +55,14 @@ type ChangeProcessorConfig struct { RelationshipCapturer relationship.Capturer // Validators validate resources according to data-plane specific rules. Validators validation.Validators - // Logger is the logger for this Change Processor. - Logger logr.Logger // EventRecorder records events for Kubernetes resources. EventRecorder record.EventRecorder // Scheme is the Kubernetes scheme. Scheme *runtime.Scheme + // ProtectedPorts are the ports that may not be configured by a listener. + ProtectedPorts map[int32]string + // Logger is the logger for this Change Processor. + Logger logr.Logger // GatewayCtlrName is the name of the Gateway controller. GatewayCtlrName string // GatewayClassName is the name of the GatewayClass resource. @@ -230,6 +232,7 @@ func (c *ChangeProcessorImpl) Process() (bool, *graph.Graph) { c.cfg.GatewayCtlrName, c.cfg.GatewayClassName, c.cfg.Validators, + c.cfg.ProtectedPorts, ) return true, c.latestGraph diff --git a/internal/mode/static/state/graph/gateway.go b/internal/mode/static/state/graph/gateway.go index 278cc996a1..15236cd0cc 100644 --- a/internal/mode/static/state/graph/gateway.go +++ b/internal/mode/static/state/graph/gateway.go @@ -95,6 +95,7 @@ func buildGateway( secretResolver *secretResolver, gc *GatewayClass, refGrantResolver *referenceGrantResolver, + protectedPorts map[int32]string, ) *Gateway { if gw == nil { return nil @@ -112,7 +113,7 @@ func buildGateway( return &Gateway{ Source: gw, - Listeners: buildListeners(gw, secretResolver, refGrantResolver), + Listeners: buildListeners(gw, secretResolver, refGrantResolver, protectedPorts), Valid: true, } } diff --git a/internal/mode/static/state/graph/gateway_listener.go b/internal/mode/static/state/graph/gateway_listener.go index 71e66a0f7c..deab5e565f 100644 --- a/internal/mode/static/state/graph/gateway_listener.go +++ b/internal/mode/static/state/graph/gateway_listener.go @@ -40,10 +40,11 @@ func buildListeners( gw *v1beta1.Gateway, secretResolver *secretResolver, refGrantResolver *referenceGrantResolver, + protectedPorts map[int32]string, ) map[string]*Listener { listeners := make(map[string]*Listener) - listenerFactory := newListenerConfiguratorFactory(gw, secretResolver, refGrantResolver) + listenerFactory := newListenerConfiguratorFactory(gw, secretResolver, refGrantResolver, protectedPorts) for _, gl := range gw.Spec.Listeners { configurator := listenerFactory.getConfiguratorForListener(gl) @@ -72,8 +73,9 @@ func newListenerConfiguratorFactory( gw *v1beta1.Gateway, secretResolver *secretResolver, refGrantResolver *referenceGrantResolver, + protectedPorts map[int32]string, ) *listenerConfiguratorFactory { - sharedPortConflictResolver := createPortConflictResolver() + sharedPortConflictResolver := createPortConflictResolver(protectedPorts) return &listenerConfiguratorFactory{ unsupportedProtocol: &listenerConfigurator{ @@ -359,22 +361,33 @@ func createHTTPSListenerValidator() listenerValidator { } } -func createPortConflictResolver() listenerConflictResolver { +func createPortConflictResolver(protectedPorts map[int32]string) listenerConflictResolver { conflictedPorts := make(map[v1beta1.PortNumber]bool) portProtocolOwner := make(map[v1beta1.PortNumber]v1beta1.ProtocolType) listenersByPort := make(map[v1beta1.PortNumber][]*Listener) - format := "Multiple listeners for the same port %d specify incompatible protocols; " + + protcolConflictFormat := "Multiple listeners for the same port %d specify incompatible protocols; " + "ensure only one protocol per port" + protectedPortsConflictFormat := "port: Invalid value: %d: port is already in use as %v" return func(l *Listener) { port := l.Source.Port + // if port is in the protected ports list, set current listener as invalid + if portName, ok := protectedPorts[int32(port)]; ok { + l.Valid = false + + conflictedConds := staticConds.NewListenerUnsupportedValue( + fmt.Sprintf(protectedPortsConflictFormat, port, portName)) + l.Conditions = append(l.Conditions, conflictedConds...) + return + } + // if port is in map of conflictedPorts then we only need to set the current listener to invalid if conflictedPorts[port] { l.Valid = false - conflictedConds := staticConds.NewListenerProtocolConflict(fmt.Sprintf(format, port)) + conflictedConds := staticConds.NewListenerProtocolConflict(fmt.Sprintf(protcolConflictFormat, port)) l.Conditions = append(l.Conditions, conflictedConds...) return } @@ -396,7 +409,7 @@ func createPortConflictResolver() listenerConflictResolver { conflictedPorts[port] = true for _, l := range listenersByPort[port] { l.Valid = false - conflictedConds := staticConds.NewListenerProtocolConflict(fmt.Sprintf(format, port)) + conflictedConds := staticConds.NewListenerProtocolConflict(fmt.Sprintf(protcolConflictFormat, port)) l.Conditions = append(l.Conditions, conflictedConds...) } } diff --git a/internal/mode/static/state/graph/gateway_test.go b/internal/mode/static/state/graph/gateway_test.go index e5fdb85d44..0aaaff69ef 100644 --- a/internal/mode/static/state/graph/gateway_test.go +++ b/internal/mode/static/state/graph/gateway_test.go @@ -145,6 +145,9 @@ func TestBuildGateway(t *testing.T) { labelSet := map[string]string{ "key": "value", } + protectedPorts := map[int32]string{ + 9113: "MetricsPort", + } listenerAllowedRoutes := v1beta1.Listener{ Name: "listener-with-allowed-routes", Hostname: helpers.GetPointer[v1beta1.Hostname]("foo.example.com"), @@ -279,6 +282,7 @@ func TestBuildGateway(t *testing.T) { // invalid listeners invalidProtocolListener := createTCPListener("invalid-protocol", "bar.example.com", 80) invalidPortListener := createHTTPListener("invalid-port", "invalid-port", 0) + invalidProtectedPortListener := createHTTPListener("invalid-protected-port", "invalid-protected-port", 9113) invalidHostnameListener := createHTTPListener("invalid-hostname", "$example.com", 80) invalidHTTPSHostnameListener := createHTTPSListener( "invalid-https-hostname", @@ -532,7 +536,13 @@ func TestBuildGateway(t *testing.T) { }, { gateway: createGateway( - gatewayCfg{listeners: []v1beta1.Listener{invalidPortListener, invalidHTTPSPortListener}}, + gatewayCfg{ + listeners: []v1beta1.Listener{ + invalidPortListener, + invalidHTTPSPortListener, + invalidProtectedPortListener, + }, + }, ), gatewayClass: validGC, expected: &Gateway{ @@ -558,6 +568,17 @@ func TestBuildGateway(t *testing.T) { {Kind: "HTTPRoute"}, }, }, + "invalid-protected-port": { + Source: invalidProtectedPortListener, + Valid: false, + Conditions: staticConds.NewListenerUnsupportedValue( + `port: Invalid value: 9113: port is already in use as MetricsPort`, + ), + Routes: map[types.NamespacedName]*Route{}, + SupportedKinds: []v1beta1.RouteGroupKind{ + {Kind: "HTTPRoute"}, + }, + }, }, Valid: true, }, @@ -843,7 +864,7 @@ func TestBuildGateway(t *testing.T) { t.Run(test.name, func(t *testing.T) { g := NewGomegaWithT(t) resolver := newReferenceGrantResolver(test.refGrants) - result := buildGateway(test.gateway, secretResolver, test.gatewayClass, resolver) + result := buildGateway(test.gateway, secretResolver, test.gatewayClass, resolver, protectedPorts) g.Expect(helpers.Diff(test.expected, result)).To(BeEmpty()) }) } diff --git a/internal/mode/static/state/graph/graph.go b/internal/mode/static/state/graph/graph.go index 8581c35c59..b39c1b4fcb 100644 --- a/internal/mode/static/state/graph/graph.go +++ b/internal/mode/static/state/graph/graph.go @@ -65,6 +65,7 @@ func BuildGraph( controllerName string, gcName string, validators validation.Validators, + protectedPorts map[int32]string, ) *Graph { processedGwClasses, gcExists := processGatewayClasses(state.GatewayClasses, gcName, controllerName) if gcExists && processedGwClasses.Winner == nil { @@ -78,7 +79,7 @@ func BuildGraph( processedGws := processGateways(state.Gateways, gcName) refGrantResolver := newReferenceGrantResolver(state.ReferenceGrants) - gw := buildGateway(processedGws.Winner, secretResolver, gc, refGrantResolver) + gw := buildGateway(processedGws.Winner, secretResolver, gc, refGrantResolver, protectedPorts) routes := buildRoutesForGateways(validators.HTTPFieldsValidator, state.HTTPRoutes, processedGws.GetAllNsNames()) bindRoutesToListeners(routes, gw, state.Namespaces) diff --git a/internal/mode/static/state/graph/graph_test.go b/internal/mode/static/state/graph/graph_test.go index 198ac5ea03..2552f595c2 100644 --- a/internal/mode/static/state/graph/graph_test.go +++ b/internal/mode/static/state/graph/graph_test.go @@ -22,6 +22,10 @@ func TestBuildGraph(t *testing.T) { controllerName = "my.controller" ) + protectedPorts := map[int32]string{ + 9113: "MetricsPort", + } + createValidRuleWithBackendRefs := func(refs []BackendRef) Rule { return Rule{ ValidMatches: true, @@ -343,6 +347,7 @@ func TestBuildGraph(t *testing.T) { controllerName, gcName, validation.Validators{HTTPFieldsValidator: &validationfakes.FakeHTTPFieldsValidator{}}, + protectedPorts, ) g.Expect(helpers.Diff(test.expected, result)).To(BeEmpty()) From 77c96348c5829ab5c612d6a488a19cf15919e707 Mon Sep 17 00:00:00 2001 From: Ciara Stacke Date: Fri, 25 Aug 2023 16:26:15 +0100 Subject: [PATCH 2/5] Review feedback --- Makefile | 2 +- cmd/gateway/commands.go | 43 +++++----- .../provisioner/static-deployment.yaml | 1 + deploy/helm-chart/README.md | 6 +- deploy/helm-chart/templates/deployment.yaml | 15 ++-- deploy/helm-chart/values.yaml | 9 +- deploy/manifests/nginx-gateway.yaml | 7 ++ docs/monitoring.md | 83 +++++++++++++------ internal/mode/static/config/config.go | 9 +- internal/mode/static/manager.go | 23 +++-- internal/mode/static/manager_test.go | 51 ++++++++++++ internal/mode/static/metrics/nginx.go | 46 +++++++++- .../mode/static/state/change_processor.go | 4 +- internal/mode/static/state/graph/gateway.go | 2 +- .../static/state/graph/gateway_listener.go | 63 +++++++------- .../state/graph/gateway_listener_test.go | 40 +++++++-- .../mode/static/state/graph/gateway_test.go | 3 +- internal/mode/static/state/graph/graph.go | 5 +- .../mode/static/state/graph/graph_test.go | 2 +- 19 files changed, 286 insertions(+), 128 deletions(-) diff --git a/Makefile b/Makefile index 670c7b3427..52f371b676 100644 --- a/Makefile +++ b/Makefile @@ -135,7 +135,7 @@ build-nkg-debug-image: debug-build build-nkg-image ## Build NKG image with debug generate-manifests: ## Generate manifests using Helm. cp $(CHART_DIR)/crds/* $(MANIFEST_DIR)/crds/ helm template nginx-gateway $(CHART_DIR) $(HELM_TEMPLATE_COMMON_ARGS) $(HELM_TEMPLATE_EXTRA_ARGS_FOR_ALL_MANIFESTS_FILE) -n nginx-gateway | cat $(strip $(MANIFEST_DIR))/namespace.yaml - > $(strip $(MANIFEST_DIR))/nginx-gateway.yaml - helm template nginx-gateway $(CHART_DIR) $(HELM_TEMPLATE_COMMON_ARGS) --set metrics.enable=false -n nginx-gateway -s templates/deployment.yaml > conformance/provisioner/static-deployment.yaml + helm template nginx-gateway $(CHART_DIR) $(HELM_TEMPLATE_COMMON_ARGS) --set metrics.disable=true -n nginx-gateway -s templates/deployment.yaml > conformance/provisioner/static-deployment.yaml helm template nginx-gateway $(CHART_DIR) $(HELM_TEMPLATE_COMMON_ARGS) -n nginx-gateway -s templates/service.yaml > $(strip $(MANIFEST_DIR))/service/loadbalancer.yaml helm template nginx-gateway $(CHART_DIR) $(HELM_TEMPLATE_COMMON_ARGS) --set service.annotations.'service\.beta\.kubernetes\.io\/aws-load-balancer-type'="nlb" -n nginx-gateway -s templates/service.yaml > $(strip $(MANIFEST_DIR))/service/loadbalancer-aws-nlb.yaml helm template nginx-gateway $(CHART_DIR) $(HELM_TEMPLATE_COMMON_ARGS) --set service.type=NodePort --set service.externalTrafficPolicy="" -n nginx-gateway -s templates/service.yaml > $(strip $(MANIFEST_DIR))/service/nodeport.yaml diff --git a/cmd/gateway/commands.go b/cmd/gateway/commands.go index 134e353cb3..29a5d78e62 100644 --- a/cmd/gateway/commands.go +++ b/cmd/gateway/commands.go @@ -24,6 +24,7 @@ const ( gatewayCtrlNameFlag = "gateway-ctlr-name" gatewayCtrlNameUsageFmt = `The name of the Gateway controller. ` + `The controller name must be of the form: DOMAIN/PATH. The controller's domain is '%s'` + gatewayFlag = "gateway" ) var ( @@ -36,6 +37,17 @@ var ( gatewayClassName = stringValidatingValue{ validator: validateResourceName, } + + // Backing values for static subcommand cli flags. + updateGCStatus bool + disableMetrics bool + metricsListenPort int + metricsSecure bool + + gateway = namespacedNameValue{} + configName = stringValidatingValue{ + validator: validateResourceName, + } ) // stringValidatingValue is a string flag value with custom validation logic. @@ -115,18 +127,6 @@ func createRootCommand() *cobra.Command { } func createStaticModeCommand() *cobra.Command { - const gatewayFlag = "gateway" - - // flag values - gateway := namespacedNameValue{} - var updateGCStatus bool - configName := stringValidatingValue{ - validator: validateResourceName, - } - var enableMetrics bool - var metricsListenPort int - var metricsSecure bool - cmd := &cobra.Command{ Use: "static-mode", Short: "Configure NGINX in the scope of a single Gateway resource", @@ -157,12 +157,12 @@ func createStaticModeCommand() *cobra.Command { } metricsConfig := config.MetricsConfig{} - if enableMetrics { + if !disableMetrics { if err := validatePort(metricsListenPort); err != nil { return fmt.Errorf("error validating metrics listen port: %w", err) } - metricsConfig.MetricsEnabled = enableMetrics - metricsConfig.MetricsPort = metricsListenPort + metricsConfig.Enabled = true + metricsConfig.Port = metricsListenPort metricsConfig.Secure = metricsSecure } @@ -213,24 +213,25 @@ func createStaticModeCommand() *cobra.Command { ) cmd.Flags().BoolVar( - &enableMetrics, - "enable-metrics", + &disableMetrics, + "metrics-disable", false, - "Enable exposing metrics in the Prometheus format.", + "Disable exposing metrics in the Prometheus format.", ) cmd.Flags().IntVar( &metricsListenPort, - "metrics-listen-port", + "metrics-port", 9113, - "Set the port where the metrics are exposed. [1023 - 65535]", + "Set the port where the metrics are exposed. Format: [1023 - 65535]", ) cmd.Flags().BoolVar( &metricsSecure, "metrics-secure-serving", false, - "Enables serving metrics via https. By default metrics are served via http.", + "Enable serving metrics via https. By default metrics are served via http."+ + " Please note that this endpoint will be secured with a self-signed certificate.", ) return cmd diff --git a/conformance/provisioner/static-deployment.yaml b/conformance/provisioner/static-deployment.yaml index 184fb4c996..fe2cbd20de 100644 --- a/conformance/provisioner/static-deployment.yaml +++ b/conformance/provisioner/static-deployment.yaml @@ -28,6 +28,7 @@ spec: - --gateway-ctlr-name=gateway.nginx.org/nginx-gateway-controller - --gatewayclass=nginx - --config=nginx-gateway-config + - --metrics-disable env: - name: POD_IP valueFrom: diff --git a/deploy/helm-chart/README.md b/deploy/helm-chart/README.md index fa1e95ef15..d826042764 100644 --- a/deploy/helm-chart/README.md +++ b/deploy/helm-chart/README.md @@ -142,6 +142,6 @@ The following tables lists the configurable parameters of the NGINX Kubernetes G | `service.externalTrafficPolicy` | The `externalTrafficPolicy` of the service. The value `Local` preserves the client source IP. | Local | | `service.annotations` | The `annotations` of the NGINX Kubernetes Gateway service. | {} | | `service.ports` | A list of ports to expose through the NGINX Kubernetes Gateway service. Update it to match the listener ports from your Gateway resource. Follows the conventional Kubernetes yaml syntax for service ports. | [ port: 80, targetPort: 80, protocol: TCP, name: http; port: 443, targetPort: 443, protocol: TCP, name: https ] | -| `metrics.enable` | Enable exposing metrics in the Prometheus format. |false | -| `metrics.port` | Sets the port where the Prometheus metrics are exposed. Format: [1024 - 65535] |9113 | -| `metrics.secure` | Configures if the metrics endpoint should be secured using https. Please note that this endpoint will be secured with a self-signed certificate. |false | +| `metrics.disable` | Disable exposing metrics in the Prometheus format. |false | +| `metrics.port` | Set the port where the Prometheus metrics are exposed. Format: [1024 - 65535] |9113 | +| `metrics.secure` | Enable serving metrics via https. By default metrics are served via http. Please note that this endpoint will be secured with a self-signed certificate. |false | diff --git a/deploy/helm-chart/templates/deployment.yaml b/deploy/helm-chart/templates/deployment.yaml index a072f37103..8bf7492e15 100644 --- a/deploy/helm-chart/templates/deployment.yaml +++ b/deploy/helm-chart/templates/deployment.yaml @@ -16,7 +16,7 @@ spec: metadata: labels: {{- include "nginx-gateway.selectorLabels" . | nindent 8 }} - {{- if .Values.metrics.enable }} + {{- if not .Values.metrics.disable }} annotations: prometheus.io/scrape: "true" prometheus.io/port: "{{ .Values.metrics.port }}" @@ -31,12 +31,13 @@ spec: - --gateway-ctlr-name={{ .Values.nginxGateway.gatewayControllerName }} - --gatewayclass={{ .Values.nginxGateway.gatewayClassName }} - --config={{ include "nginx-gateway.config-name" . }} - {{- if .Values.metrics.enable }} - - --enable-metrics=true - - --metrics-listen-port={{ .Values.metrics.port }} + {{- if not .Values.metrics.disable }} + - --metrics-port={{ .Values.metrics.port }} {{- if .Values.metrics.secure }} - - --metrics-secure-serving=true + - --metrics-secure-serving {{- end }} + {{- else }} + - --metrics-disable {{- end }} env: - name: POD_IP @@ -50,9 +51,9 @@ spec: image: {{ .Values.nginxGateway.image.repository }}:{{ .Values.nginxGateway.image.tag | default .Chart.AppVersion }} imagePullPolicy: {{ .Values.nginxGateway.image.pullPolicy }} name: nginx-gateway - {{- if .Values.metrics.enable }} + {{- if not .Values.metrics.disable }} ports: - - name: prometheus + - name: metrics containerPort: {{ .Values.metrics.port }} {{- end }} securityContext: diff --git a/deploy/helm-chart/values.yaml b/deploy/helm-chart/values.yaml index be198935fa..fd3a77007e 100644 --- a/deploy/helm-chart/values.yaml +++ b/deploy/helm-chart/values.yaml @@ -56,9 +56,10 @@ service: name: https metrics: - ## Expose metrics in the Prometheus format. - enable: false - ## Configures the port to scrape the metrics. + ## Disable exposing metrics in the Prometheus format. + disable: false + ## Set the port where the Prometheus metrics are exposed. Format: [1024 - 65535] port: 9113 - ## Configures if the metrics endpoint should be secured using https. + ## Enable serving metrics via https. By default metrics are served via http. + ## Please note that this endpoint will be secured with a self-signed certificate. secure: false diff --git a/deploy/manifests/nginx-gateway.yaml b/deploy/manifests/nginx-gateway.yaml index 3bd5059ecd..129147c3db 100644 --- a/deploy/manifests/nginx-gateway.yaml +++ b/deploy/manifests/nginx-gateway.yaml @@ -122,6 +122,9 @@ spec: labels: app.kubernetes.io/name: nginx-gateway app.kubernetes.io/instance: nginx-gateway + annotations: + prometheus.io/scrape: "true" + prometheus.io/port: "9113" spec: containers: - args: @@ -129,6 +132,7 @@ spec: - --gateway-ctlr-name=gateway.nginx.org/nginx-gateway-controller - --gatewayclass=nginx - --config=nginx-gateway-config + - --metrics-port=9113 env: - name: POD_IP valueFrom: @@ -141,6 +145,9 @@ spec: image: ghcr.io/nginxinc/nginx-kubernetes-gateway:edge imagePullPolicy: Always name: nginx-gateway + ports: + - name: metrics + containerPort: 9113 securityContext: allowPrivilegeEscalation: false capabilities: diff --git a/docs/monitoring.md b/docs/monitoring.md index 0ac600d0ce..9a9f8f5e5e 100644 --- a/docs/monitoring.md +++ b/docs/monitoring.md @@ -2,37 +2,39 @@ The NGINX Kubernetes Gateway exposes a number of metrics in the [Prometheus](https://prometheus.io/) format. Those include NGINX and the controller-runtime metrics. These are delivered using a metrics server orchestrated by the -controller-runtime package. +controller-runtime package. Metrics are enabled by default, and are served via http on port `9113`. -## Enabling Metrics +> **Note:** By default metrics are served via http. Please note that if serving metrics via https is enabled, this +> endpoint will be secured with a self-signed certificate. Since the metrics server is using a self-signed certificate, +> the Prometheus pod scrape configuration will also require the `insecure_skip_verify` flag set. See +> [the Prometheus documentation](https://prometheus.io/docs/prometheus/latest/configuration/configuration/#tls_config). + +## Changing the default Metrics configuration ### Using Helm -If you're using *Helm* to install the NGINX Kubernetes Gateway, to enable Prometheus metrics, configure the `metrics.*` -parameters of the Helm chart. See the [Helm README](/deploy/helm-chart/README.md). Please note that if `metrics.secure` -is set to true, as the metrics server is using a self-signed certificate, the Prometheus pod scrape configuration will -also require the `insecure_skip_verify` flag set. See [the Prometheus documentation](https://prometheus.io/docs/prometheus/latest/configuration/configuration/#tls_config). +If you're using *Helm* to install the NGINX Kubernetes Gateway, set the `metrics.*` parameters to the required values +for your environment. See the [Helm README](/deploy/helm-chart/README.md). ### Using Manifests -If you're using *Kubernetes manifests* to install the NGINX Kubernetes Gateway, modify the [manifest](/deploy/manifests/nginx-gateway.yaml) -to enable Prometheus metrics to enable the following: +If you're using *Kubernetes manifests* to install NGINX Kubernetes Gateway, you can modify the +[manifest](/deploy/manifests/nginx-gateway.yaml) to change the default metrics configuration: + +#### Disabling metrics + +1. Set the `-metrics-disable` [command-line argument](/docs/cli-help.md) to `true` and remove the other `-metrics-*` + command line arguments. -1. Run the NGINX Kubernetes Gateway with the `-enable-metrics` [command-line argument](/docs/cli-help.md). - As a result, the NGINX Kubernetes Gateway will expose NGINX metrics in the Prometheus format via the path `/metrics` - on port `9113` (customizable via the `-metrics-listen-port` [command-line argument](/docs/cli-help.md)) using http - (customizable via the `-metrics-secure-serving` [command-line argument](/docs/cli-help.md)). -2. Add the Prometheus port to the list of the ports of the NGINX Kubernetes Gateway container in the template of the - NGINX Kubernetes Gateway pod: +2. Remove the metrics port entry from the list of the ports of the NGINX Kubernetes Gateway container in the template + of the NGINX Kubernetes Gateway Pod: ```yaml - - name: prometheus + - name: metrics containerPort: 9113 ``` -3. Make Prometheus aware of the NGINX Kubernetes Gateway targets by adding the following annotations to the template of - the NGINX Kubernetes Gateway pod (note: this assumes your Prometheus is configured to discover targets by analyzing the - annotations of pods): +3. Remove the following annotations from the template of the NGINX Kubernetes Gateway Pod: ```yaml annotations: @@ -40,25 +42,52 @@ to enable Prometheus metrics to enable the following: prometheus.io/port: "9113" ``` - If the `-metrics-secure-serving` flag is enabled, the following annotation will also needed to be added to the pod spec: +#### Changing the default port + +1. Set the `-metrics-port` [command-line argument](/docs/cli-help.md) to the required value. + +2. Change the metrics port entry in the list of the ports of the NGINX Kubernetes Gateway container in the template + of the NGINX Kubernetes Gateway Pod: + + ```yaml + - name: metrics + containerPort: + ``` + +3. Change the following annotation in the template of the NGINX Kubernetes Gateway Pod: - ```yaml - prometheus.io/scheme: "https" - ``` + ```yaml + annotations: + <...> + prometheus.io/port: "" + <...> + ``` + +#### Enable serving metrics via https + +1. Set the `-metrics-secure-serving` [command-line argument](/docs/cli-help.md) to `true`. - As the metrics server is using a self-signed certificate, the Prometheus pod scrape configuration will also require the - `insecure_skip_verify` flag set. See [the Prometheus documentation](https://prometheus.io/docs/prometheus/latest/configuration/configuration/#tls_config) +2. Add the following annotation in the template of the NGINX Kubernetes Gateway Pod: + + ```yaml + annotations: + <...> + prometheus.io/scheme: "https" + <...> + ``` ## Available Metrics -The NGINX Kubernetes Gateway exports the following metrics: +NGINX Kubernetes Gateway exports the following metrics: - NGINX metrics: - Exported by NGINX. Refer to the [NGINX Prometheus Exporter developer docs](https://github.com/nginxinc/nginx-prometheus-exporter#metrics-for-nginx-oss) + - These metrics have the namespace `nginx_kubernetes_gateway`, and include the label `class` which is set to the + Gateway class of NKG. For example, `nginx_kubernetes_gateway_connections_accepted{class="nginx"}`. - [controller-runtime](https://github.com/kubernetes-sigs/controller-runtime) metrics. These include: - - Total number of reconcilation errors per controller + - Total number of reconciliation errors per controller - Length of reconcile queue per controller - - Reconcilation latency + - Reconciliation latency - Usual resource metrics such as CPU, memory usage, file descriptor usage - Go runtime metrics such as number of Go routines, GC duration, and Go version information diff --git a/internal/mode/static/config/config.go b/internal/mode/static/config/config.go index 11c2bc8c92..09bdcf1240 100644 --- a/internal/mode/static/config/config.go +++ b/internal/mode/static/config/config.go @@ -30,11 +30,12 @@ type Config struct { MetricsConfig MetricsConfig } +// MetricsConfig specifies the metrics config. type MetricsConfig struct { - // MetricsPort is the port the metrics should be exposed on. - MetricsPort int - // MetricsEnabled is the flag for toggling metrics on or off. - MetricsEnabled bool + // Port is the port the metrics should be exposed on. + Port int + // Enabled is the flag for toggling metrics on or off. + Enabled bool // Secure is the flag for toggling the metrics endpoint to https. Secure bool } diff --git a/internal/mode/static/manager.go b/internal/mode/static/manager.go index 26ed9f4750..41fa4c9c2d 100644 --- a/internal/mode/static/manager.go +++ b/internal/mode/static/manager.go @@ -29,7 +29,7 @@ import ( "github.com/nginxinc/nginx-kubernetes-gateway/internal/framework/events" "github.com/nginxinc/nginx-kubernetes-gateway/internal/framework/status" "github.com/nginxinc/nginx-kubernetes-gateway/internal/mode/static/config" - nkgMetrics "github.com/nginxinc/nginx-kubernetes-gateway/internal/mode/static/metrics" + nkgmetrics "github.com/nginxinc/nginx-kubernetes-gateway/internal/mode/static/metrics" ngxcfg "github.com/nginxinc/nginx-kubernetes-gateway/internal/mode/static/nginx/config" ngxvalidation "github.com/nginxinc/nginx-kubernetes-gateway/internal/mode/static/nginx/config/validation" "github.com/nginxinc/nginx-kubernetes-gateway/internal/mode/static/nginx/file" @@ -60,7 +60,7 @@ func StartManager(cfg config.Config) error { options := manager.Options{ Scheme: scheme, Logger: logger, - Metrics: getMetricsConfig(cfg.MetricsConfig), + Metrics: getMetricsOptions(cfg.MetricsConfig), } eventCh := make(chan interface{}) @@ -164,7 +164,7 @@ func StartManager(cfg config.Config) error { // protectedPorts is the map of ports that may not be configured by a listener, and the name of what it is used for protectedPorts := map[int32]string{ - int32(cfg.MetricsConfig.MetricsPort): "MetricsPort", + int32(cfg.MetricsConfig.Port): "MetricsPort", } processor := state.NewChangeProcessorImpl(state.ChangeProcessorConfig{ @@ -231,8 +231,8 @@ func StartManager(cfg config.Config) error { return fmt.Errorf("cannot register event loop: %w", err) } - if cfg.MetricsConfig.MetricsEnabled { - err = configureNginxMetrics(cfg.GatewayClassName) + if cfg.MetricsConfig.Enabled { + err = configureNginxMetrics(ctx, cfg.GatewayClassName) if err != nil { return fmt.Errorf("cannot register nginx metrics: %w", err) } @@ -290,24 +290,23 @@ func setInitialConfig( return updateControlPlane(&config, logger, eventRecorder, configName, logLevelSetter) } -func configureNginxMetrics(gatewayClassName string) error { +func configureNginxMetrics(ctx context.Context, gatewayClassName string) error { constLabels := map[string]string{"class": gatewayClassName} - ngxCollector, err := nkgMetrics.NewNginxMetricsClient(constLabels) + ngxCollector, err := nkgmetrics.NewNginxMetricsCollector(ctx, constLabels) if err != nil { return fmt.Errorf("cannot get NGINX metrics: %w", err) } - metrics.Registry.MustRegister(ngxCollector) - return nil + return metrics.Registry.Register(ngxCollector) } -func getMetricsConfig(cfg config.MetricsConfig) metricsserver.Options { +func getMetricsOptions(cfg config.MetricsConfig) metricsserver.Options { metricsOptions := metricsserver.Options{BindAddress: "0"} - if cfg.MetricsEnabled { + if cfg.Enabled { if cfg.Secure { metricsOptions.SecureServing = true } - metricsOptions.BindAddress = fmt.Sprintf(":%v", cfg.MetricsPort) + metricsOptions.BindAddress = fmt.Sprintf(":%v", cfg.Port) } return metricsOptions diff --git a/internal/mode/static/manager_test.go b/internal/mode/static/manager_test.go index 4fbe4c9f5d..07b73f1c4f 100644 --- a/internal/mode/static/manager_test.go +++ b/internal/mode/static/manager_test.go @@ -9,7 +9,10 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/types" "sigs.k8s.io/controller-runtime/pkg/client" + metricsserver "sigs.k8s.io/controller-runtime/pkg/metrics/server" gatewayv1beta1 "sigs.k8s.io/gateway-api/apis/v1beta1" + + "github.com/nginxinc/nginx-kubernetes-gateway/internal/mode/static/config" ) func TestPrepareFirstEventBatchPreparerArgs(t *testing.T) { @@ -69,3 +72,51 @@ func TestPrepareFirstEventBatchPreparerArgs(t *testing.T) { }) } } + +func TestGetMetricsOptions(t *testing.T) { + tests := []struct { + name string + expectedOptions metricsserver.Options + metricsConfig config.MetricsConfig + }{ + { + name: "Metrics disabled", + metricsConfig: config.MetricsConfig{Enabled: false}, + expectedOptions: metricsserver.Options{BindAddress: "0"}, + }, + { + name: "Metrics enabled, not secure", + metricsConfig: config.MetricsConfig{ + Port: 9113, + Enabled: true, + Secure: false, + }, + expectedOptions: metricsserver.Options{ + SecureServing: false, + BindAddress: ":9113", + }, + }, + { + name: "Metrics enabled, secure", + metricsConfig: config.MetricsConfig{ + Port: 9113, + Enabled: true, + Secure: true, + }, + expectedOptions: metricsserver.Options{ + SecureServing: true, + BindAddress: ":9113", + }, + }, + } + + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + g := NewGomegaWithT(t) + + metricsServerOptions := getMetricsOptions(test.metricsConfig) + + g.Expect(metricsServerOptions).To(Equal(test.expectedOptions)) + }) + } +} diff --git a/internal/mode/static/metrics/nginx.go b/internal/mode/static/metrics/nginx.go index 30d371aeb3..2619cee43c 100644 --- a/internal/mode/static/metrics/nginx.go +++ b/internal/mode/static/metrics/nginx.go @@ -4,6 +4,9 @@ import ( "context" "net" "net/http" + "time" + + "k8s.io/apimachinery/pkg/util/wait" prometheusClient "github.com/nginxinc/nginx-prometheus-exporter/client" nginxCollector "github.com/nginxinc/nginx-prometheus-exporter/collector" @@ -11,13 +14,18 @@ import ( ) const ( - nginxStatusSock = "/var/run/nginx/nginx-status.sock" - nginxStatusURI = "http://config-status/stub_status" + nginxStatusSock = "/var/run/nginx/nginx-status.sock" + nginxStatusURI = "http://config-status/stub_status" + nginxStatusSockTimeout = 10 * time.Second ) -// NewNginxMetricsClient creates an NginxClient to fetch stats from NGINX over a unix socket -func NewNginxMetricsClient(constLabels map[string]string) (prometheus.Collector, error) { +// NewNginxMetricsCollector creates an NginxCollector which fetches stats from NGINX over a unix socket +func NewNginxMetricsCollector(ctx context.Context, constLabels map[string]string) (prometheus.Collector, error) { httpClient := getSocketClient(nginxStatusSock) + err := ensureStatusSockActive(ctx, httpClient, nginxStatusSockTimeout) + if err != nil { + return nil, err + } client, err := prometheusClient.NewNginxClient(&httpClient, nginxStatusURI) if err != nil { return nil, err @@ -35,3 +43,33 @@ func getSocketClient(sockPath string) http.Client { }, } } + +// ensureStatusSockActive waits until NGINX is serving metrics +func ensureStatusSockActive(ctx context.Context, httpClient http.Client, timeout time.Duration) error { + ctx, cancel := context.WithTimeout(ctx, timeout) + defer cancel() + + req, err := http.NewRequestWithContext(ctx, http.MethodGet, nginxStatusURI, nil) + if err != nil { + return err + } + + err = wait.PollUntilContextCancel( + ctx, + 500*time.Millisecond, + true, /* poll immediately */ + func(ctx context.Context) (bool, error) { + resp, err := httpClient.Do(req) + if err != nil { + //lint:ignore nilerr reason + return false, nil + } + resp.Body.Close() + return true, nil + }) + if err != nil { + return err + } + + return nil +} diff --git a/internal/mode/static/state/change_processor.go b/internal/mode/static/state/change_processor.go index 743cb6214c..6ccf00d751 100644 --- a/internal/mode/static/state/change_processor.go +++ b/internal/mode/static/state/change_processor.go @@ -59,8 +59,8 @@ type ChangeProcessorConfig struct { EventRecorder record.EventRecorder // Scheme is the Kubernetes scheme. Scheme *runtime.Scheme - // ProtectedPorts are the ports that may not be configured by a listener. - ProtectedPorts map[int32]string + // ProtectedPorts are the ports that may not be configured by a listener with a descriptive name of the ports. + ProtectedPorts graph.ProtectedPorts // Logger is the logger for this Change Processor. Logger logr.Logger // GatewayCtlrName is the name of the Gateway controller. diff --git a/internal/mode/static/state/graph/gateway.go b/internal/mode/static/state/graph/gateway.go index 15236cd0cc..908aa7ef19 100644 --- a/internal/mode/static/state/graph/gateway.go +++ b/internal/mode/static/state/graph/gateway.go @@ -95,7 +95,7 @@ func buildGateway( secretResolver *secretResolver, gc *GatewayClass, refGrantResolver *referenceGrantResolver, - protectedPorts map[int32]string, + protectedPorts ProtectedPorts, ) *Gateway { if gw == nil { return nil diff --git a/internal/mode/static/state/graph/gateway_listener.go b/internal/mode/static/state/graph/gateway_listener.go index deab5e565f..f8373d299f 100644 --- a/internal/mode/static/state/graph/gateway_listener.go +++ b/internal/mode/static/state/graph/gateway_listener.go @@ -40,7 +40,7 @@ func buildListeners( gw *v1beta1.Gateway, secretResolver *secretResolver, refGrantResolver *referenceGrantResolver, - protectedPorts map[int32]string, + protectedPorts ProtectedPorts, ) map[string]*Listener { listeners := make(map[string]*Listener) @@ -73,9 +73,9 @@ func newListenerConfiguratorFactory( gw *v1beta1.Gateway, secretResolver *secretResolver, refGrantResolver *referenceGrantResolver, - protectedPorts map[int32]string, + protectedPorts ProtectedPorts, ) *listenerConfiguratorFactory { - sharedPortConflictResolver := createPortConflictResolver(protectedPorts) + sharedPortConflictResolver := createPortConflictResolver() return &listenerConfiguratorFactory{ unsupportedProtocol: &listenerConfigurator{ @@ -95,7 +95,7 @@ func newListenerConfiguratorFactory( validateListenerAllowedRouteKind, validateListenerLabelSelector, validateListenerHostname, - validateHTTPListener, + createHTTPListenerValidator(protectedPorts), }, conflictResolvers: []listenerConflictResolver{ sharedPortConflictResolver, @@ -106,7 +106,7 @@ func newListenerConfiguratorFactory( validateListenerAllowedRouteKind, validateListenerLabelSelector, validateListenerHostname, - createHTTPSListenerValidator(), + createHTTPSListenerValidator(protectedPorts), }, conflictResolvers: []listenerConflictResolver{ sharedPortConflictResolver, @@ -277,33 +277,41 @@ func validateListenerLabelSelector(listener v1beta1.Listener) []conditions.Condi return nil } -func validateHTTPListener(listener v1beta1.Listener) []conditions.Condition { - if err := validateListenerPort(listener.Port); err != nil { - path := field.NewPath("port") - valErr := field.Invalid(path, listener.Port, err.Error()) - return staticConds.NewListenerUnsupportedValue(valErr.Error()) - } +func createHTTPListenerValidator(protectedPorts ProtectedPorts) listenerValidator { + return func(listener v1beta1.Listener) []conditions.Condition { + var conds []conditions.Condition - if listener.TLS != nil { - panicForBrokenWebhookAssumption(fmt.Errorf("tls is not nil for HTTP listener %q", listener.Name)) - } + if err := validateListenerPort(listener.Port, protectedPorts); err != nil { + path := field.NewPath("port") + valErr := field.Invalid(path, listener.Port, err.Error()) + conds = append(conds, staticConds.NewListenerUnsupportedValue(valErr.Error())...) + } - return nil + if listener.TLS != nil { + panicForBrokenWebhookAssumption(fmt.Errorf("tls is not nil for HTTP listener %q", listener.Name)) + } + + return conds + } } -func validateListenerPort(port v1beta1.PortNumber) error { +func validateListenerPort(port v1beta1.PortNumber, protectedPorts ProtectedPorts) error { if port < 1 || port > 65535 { return errors.New("port must be between 1-65535") } + if portName, ok := protectedPorts[int32(port)]; ok { + return fmt.Errorf("port is already in use as %v", portName) + } + return nil } -func createHTTPSListenerValidator() listenerValidator { +func createHTTPSListenerValidator(protectedPorts ProtectedPorts) listenerValidator { return func(listener v1beta1.Listener) []conditions.Condition { var conds []conditions.Condition - if err := validateListenerPort(listener.Port); err != nil { + if err := validateListenerPort(listener.Port, protectedPorts); err != nil { path := field.NewPath("port") valErr := field.Invalid(path, listener.Port, err.Error()) conds = append(conds, staticConds.NewListenerUnsupportedValue(valErr.Error())...) @@ -361,33 +369,22 @@ func createHTTPSListenerValidator() listenerValidator { } } -func createPortConflictResolver(protectedPorts map[int32]string) listenerConflictResolver { +func createPortConflictResolver() listenerConflictResolver { conflictedPorts := make(map[v1beta1.PortNumber]bool) portProtocolOwner := make(map[v1beta1.PortNumber]v1beta1.ProtocolType) listenersByPort := make(map[v1beta1.PortNumber][]*Listener) - protcolConflictFormat := "Multiple listeners for the same port %d specify incompatible protocols; " + + format := "Multiple listeners for the same port %d specify incompatible protocols; " + "ensure only one protocol per port" - protectedPortsConflictFormat := "port: Invalid value: %d: port is already in use as %v" return func(l *Listener) { port := l.Source.Port - // if port is in the protected ports list, set current listener as invalid - if portName, ok := protectedPorts[int32(port)]; ok { - l.Valid = false - - conflictedConds := staticConds.NewListenerUnsupportedValue( - fmt.Sprintf(protectedPortsConflictFormat, port, portName)) - l.Conditions = append(l.Conditions, conflictedConds...) - return - } - // if port is in map of conflictedPorts then we only need to set the current listener to invalid if conflictedPorts[port] { l.Valid = false - conflictedConds := staticConds.NewListenerProtocolConflict(fmt.Sprintf(protcolConflictFormat, port)) + conflictedConds := staticConds.NewListenerProtocolConflict(fmt.Sprintf(format, port)) l.Conditions = append(l.Conditions, conflictedConds...) return } @@ -409,7 +406,7 @@ func createPortConflictResolver(protectedPorts map[int32]string) listenerConflic conflictedPorts[port] = true for _, l := range listenersByPort[port] { l.Valid = false - conflictedConds := staticConds.NewListenerProtocolConflict(fmt.Sprintf(protcolConflictFormat, port)) + conflictedConds := staticConds.NewListenerProtocolConflict(fmt.Sprintf(format, port)) l.Conditions = append(l.Conditions, conflictedConds...) } } diff --git a/internal/mode/static/state/graph/gateway_listener_test.go b/internal/mode/static/state/graph/gateway_listener_test.go index 7700cdd9ec..9b3073f4fb 100644 --- a/internal/mode/static/state/graph/gateway_listener_test.go +++ b/internal/mode/static/state/graph/gateway_listener_test.go @@ -14,6 +14,8 @@ import ( ) func TestValidateHTTPListener(t *testing.T) { + protectedPorts := ProtectedPorts{9113: "MetricsPort"} + tests := []struct { l v1beta1.Listener name string @@ -33,13 +35,25 @@ func TestValidateHTTPListener(t *testing.T) { expected: staticConds.NewListenerUnsupportedValue(`port: Invalid value: 0: port must be between 1-65535`), name: "invalid port", }, + { + l: v1beta1.Listener{ + Port: 9113, + }, + expected: staticConds.NewListenerUnsupportedValue( + `port: Invalid value: 9113: port is already in use as MetricsPort`, + ), + name: "invalid protected port", + }, } for _, test := range tests { t.Run(test.name, func(t *testing.T) { g := NewGomegaWithT(t) - result := validateHTTPListener(test.l) + v := createHTTPListenerValidator(protectedPorts) + + result := v(test.l) + g.Expect(result).To(Equal(test.expected)) }) } @@ -67,6 +81,8 @@ func TestValidateHTTPSListener(t *testing.T) { Namespace: (*v1beta1.Namespace)(helpers.GetPointer(secretNs)), } + protectedPorts := ProtectedPorts{9113: "MetricsPort"} + tests := []struct { l v1beta1.Listener name string @@ -94,6 +110,19 @@ func TestValidateHTTPSListener(t *testing.T) { expected: staticConds.NewListenerUnsupportedValue(`port: Invalid value: 0: port must be between 1-65535`), name: "invalid port", }, + { + l: v1beta1.Listener{ + Port: 9113, + TLS: &v1beta1.GatewayTLSConfig{ + Mode: helpers.GetTLSModePointer(v1beta1.TLSModeTerminate), + CertificateRefs: []v1beta1.SecretObjectReference{validSecretRef}, + }, + }, + expected: staticConds.NewListenerUnsupportedValue( + `port: Invalid value: 9113: port is already in use as MetricsPort`, + ), + name: "invalid protected port", + }, { l: v1beta1.Listener{ Port: 443, @@ -164,7 +193,7 @@ func TestValidateHTTPSListener(t *testing.T) { t.Run(test.name, func(t *testing.T) { g := NewGomegaWithT(t) - v := createHTTPSListenerValidator() + v := createHTTPSListenerValidator(protectedPorts) result := v(test.l) g.Expect(result).To(Equal(test.expected)) @@ -388,19 +417,20 @@ func TestValidateListenerLabelSelector(t *testing.T) { func TestValidateListenerPort(t *testing.T) { validPorts := []v1beta1.PortNumber{1, 80, 443, 1000, 50000, 65535} - invalidPorts := []v1beta1.PortNumber{-1, 0, 65536, 80000} + invalidPorts := []v1beta1.PortNumber{-1, 0, 65536, 80000, 9113} + protectedPorts := ProtectedPorts{9113: "MetricsPort"} for _, p := range validPorts { t.Run(fmt.Sprintf("valid port %d", p), func(t *testing.T) { g := NewWithT(t) - g.Expect(validateListenerPort(p)).To(Succeed()) + g.Expect(validateListenerPort(p, protectedPorts)).To(Succeed()) }) } for _, p := range invalidPorts { t.Run(fmt.Sprintf("invalid port %d", p), func(t *testing.T) { g := NewWithT(t) - g.Expect(validateListenerPort(p)).ToNot(Succeed()) + g.Expect(validateListenerPort(p, protectedPorts)).ToNot(Succeed()) }) } } diff --git a/internal/mode/static/state/graph/gateway_test.go b/internal/mode/static/state/graph/gateway_test.go index 0aaaff69ef..8cfebea0e4 100644 --- a/internal/mode/static/state/graph/gateway_test.go +++ b/internal/mode/static/state/graph/gateway_test.go @@ -145,7 +145,7 @@ func TestBuildGateway(t *testing.T) { labelSet := map[string]string{ "key": "value", } - protectedPorts := map[int32]string{ + protectedPorts := ProtectedPorts{ 9113: "MetricsPort", } listenerAllowedRoutes := v1beta1.Listener{ @@ -574,7 +574,6 @@ func TestBuildGateway(t *testing.T) { Conditions: staticConds.NewListenerUnsupportedValue( `port: Invalid value: 9113: port is already in use as MetricsPort`, ), - Routes: map[types.NamespacedName]*Route{}, SupportedKinds: []v1beta1.RouteGroupKind{ {Kind: "HTTPRoute"}, }, diff --git a/internal/mode/static/state/graph/graph.go b/internal/mode/static/state/graph/graph.go index b39c1b4fcb..cc9ab1da4b 100644 --- a/internal/mode/static/state/graph/graph.go +++ b/internal/mode/static/state/graph/graph.go @@ -43,6 +43,9 @@ type Graph struct { ReferencedSecrets map[types.NamespacedName]*Secret } +// ProtectedPorts are the ports that may not be configured by a listener with a descriptive name of each port. +type ProtectedPorts map[int32]string + // IsReferenced returns true if the Graph references the resource. func (g *Graph) IsReferenced(resourceType client.Object, nsname types.NamespacedName) bool { // FIMXE(pleshakov): For now, only works with Secrets. @@ -65,7 +68,7 @@ func BuildGraph( controllerName string, gcName string, validators validation.Validators, - protectedPorts map[int32]string, + protectedPorts ProtectedPorts, ) *Graph { processedGwClasses, gcExists := processGatewayClasses(state.GatewayClasses, gcName, controllerName) if gcExists && processedGwClasses.Winner == nil { diff --git a/internal/mode/static/state/graph/graph_test.go b/internal/mode/static/state/graph/graph_test.go index 2552f595c2..efe1bc5c2a 100644 --- a/internal/mode/static/state/graph/graph_test.go +++ b/internal/mode/static/state/graph/graph_test.go @@ -22,7 +22,7 @@ func TestBuildGraph(t *testing.T) { controllerName = "my.controller" ) - protectedPorts := map[int32]string{ + protectedPorts := ProtectedPorts{ 9113: "MetricsPort", } From 9fc7c6c2cc49f67c4ca675cbd1d781e8ac09b3a7 Mon Sep 17 00:00:00 2001 From: Ciara Stacke Date: Mon, 28 Aug 2023 12:43:50 +0100 Subject: [PATCH 3/5] Add check for NGINX process before starting manager --- docs/cli-help.md | 2 +- docs/monitoring.md | 5 ++- internal/mode/static/manager.go | 14 ++++--- internal/mode/static/metrics/nginx.go | 38 +------------------ internal/mode/static/nginx/runtime/manager.go | 7 ++++ 5 files changed, 21 insertions(+), 45 deletions(-) diff --git a/docs/cli-help.md b/docs/cli-help.md index 227e0ba8be..fb1adeb9de 100644 --- a/docs/cli-help.md +++ b/docs/cli-help.md @@ -20,6 +20,6 @@ Flags: | `gatewayclass` | `string` | The name of the GatewayClass resource. Every NGINX Gateway must have a unique corresponding GatewayClass resource. | | `gateway` | `string` | The namespaced name of the Gateway resource to use. Must be of the form: `NAMESPACE/NAME`. If not specified, the control plane will process all Gateways for the configured GatewayClass. However, among them, it will choose the oldest resource by creation timestamp. If the timestamps are equal, it will choose the resource that appears first in alphabetical order by {namespace}/{name}. | | `config` | `string` | The name of the NginxGateway resource to be used for this controller's dynamic configuration. Lives in the same Namespace as the controller. | -| `enable-metrics` | `bool` | Enable metrics reporting in the Prometheus format. (default false) | +| `metrics-disable` | `bool` | Disable exposing metrics in the Prometheus format. (default false) | | `metrics-listen-port` | `int` | Sets the port where the Prometheus metrics are exposed. Format: `[1024 - 65535]` (default `9113`) | | `metrics-secure-serving` | `bool` | Configures if the metrics endpoint should be secured using https. Please note that this endpoint will be secured with a self-signed certificate. (default false) | diff --git a/docs/monitoring.md b/docs/monitoring.md index 9a9f8f5e5e..5e5862157d 100644 --- a/docs/monitoring.md +++ b/docs/monitoring.md @@ -4,9 +4,10 @@ The NGINX Kubernetes Gateway exposes a number of metrics in the [Prometheus](htt include NGINX and the controller-runtime metrics. These are delivered using a metrics server orchestrated by the controller-runtime package. Metrics are enabled by default, and are served via http on port `9113`. -> **Note:** By default metrics are served via http. Please note that if serving metrics via https is enabled, this +> **Note** +> By default metrics are served via http. Please note that if serving metrics via https is enabled, this > endpoint will be secured with a self-signed certificate. Since the metrics server is using a self-signed certificate, -> the Prometheus pod scrape configuration will also require the `insecure_skip_verify` flag set. See +> the Prometheus Pod scrape configuration will also require the `insecure_skip_verify` flag set. See > [the Prometheus documentation](https://prometheus.io/docs/prometheus/latest/configuration/configuration/#tls_config). ## Changing the default Metrics configuration diff --git a/internal/mode/static/manager.go b/internal/mode/static/manager.go index 41fa4c9c2d..01ca2da11b 100644 --- a/internal/mode/static/manager.go +++ b/internal/mode/static/manager.go @@ -231,10 +231,14 @@ func StartManager(cfg config.Config) error { return fmt.Errorf("cannot register event loop: %w", err) } + // Ensure NGINX is running before registering metrics & starting the manager. + if err := ngxruntime.EnsureNginxRunning(ctx); err != nil { + return fmt.Errorf("NGINX is not running: %w", err) + } + if cfg.MetricsConfig.Enabled { - err = configureNginxMetrics(ctx, cfg.GatewayClassName) - if err != nil { - return fmt.Errorf("cannot register nginx metrics: %w", err) + if err := configureNginxMetrics(cfg.GatewayClassName); err != nil { + return err } } @@ -290,9 +294,9 @@ func setInitialConfig( return updateControlPlane(&config, logger, eventRecorder, configName, logLevelSetter) } -func configureNginxMetrics(ctx context.Context, gatewayClassName string) error { +func configureNginxMetrics(gatewayClassName string) error { constLabels := map[string]string{"class": gatewayClassName} - ngxCollector, err := nkgmetrics.NewNginxMetricsCollector(ctx, constLabels) + ngxCollector, err := nkgmetrics.NewNginxMetricsCollector(constLabels) if err != nil { return fmt.Errorf("cannot get NGINX metrics: %w", err) } diff --git a/internal/mode/static/metrics/nginx.go b/internal/mode/static/metrics/nginx.go index 2619cee43c..33946722d2 100644 --- a/internal/mode/static/metrics/nginx.go +++ b/internal/mode/static/metrics/nginx.go @@ -6,8 +6,6 @@ import ( "net/http" "time" - "k8s.io/apimachinery/pkg/util/wait" - prometheusClient "github.com/nginxinc/nginx-prometheus-exporter/client" nginxCollector "github.com/nginxinc/nginx-prometheus-exporter/collector" "github.com/prometheus/client_golang/prometheus" @@ -20,12 +18,8 @@ const ( ) // NewNginxMetricsCollector creates an NginxCollector which fetches stats from NGINX over a unix socket -func NewNginxMetricsCollector(ctx context.Context, constLabels map[string]string) (prometheus.Collector, error) { +func NewNginxMetricsCollector(constLabels map[string]string) (prometheus.Collector, error) { httpClient := getSocketClient(nginxStatusSock) - err := ensureStatusSockActive(ctx, httpClient, nginxStatusSockTimeout) - if err != nil { - return nil, err - } client, err := prometheusClient.NewNginxClient(&httpClient, nginxStatusURI) if err != nil { return nil, err @@ -43,33 +37,3 @@ func getSocketClient(sockPath string) http.Client { }, } } - -// ensureStatusSockActive waits until NGINX is serving metrics -func ensureStatusSockActive(ctx context.Context, httpClient http.Client, timeout time.Duration) error { - ctx, cancel := context.WithTimeout(ctx, timeout) - defer cancel() - - req, err := http.NewRequestWithContext(ctx, http.MethodGet, nginxStatusURI, nil) - if err != nil { - return err - } - - err = wait.PollUntilContextCancel( - ctx, - 500*time.Millisecond, - true, /* poll immediately */ - func(ctx context.Context) (bool, error) { - resp, err := httpClient.Do(req) - if err != nil { - //lint:ignore nilerr reason - return false, nil - } - resp.Body.Close() - return true, nil - }) - if err != nil { - return err - } - - return nil -} diff --git a/internal/mode/static/nginx/runtime/manager.go b/internal/mode/static/nginx/runtime/manager.go index 88fa44afbb..7e8768ea73 100644 --- a/internal/mode/static/nginx/runtime/manager.go +++ b/internal/mode/static/nginx/runtime/manager.go @@ -70,6 +70,13 @@ func (m *ManagerImpl) Reload(ctx context.Context) error { return nil } +func EnsureNginxRunning(ctx context.Context) error { + if _, err := findMainProcess(ctx, os.Stat, os.ReadFile, pidFileTimeout); err != nil { + return fmt.Errorf("failed to find NGINX main process: %w", err) + } + return nil +} + func findMainProcess( ctx context.Context, checkFile checkFileFunc, From fa2902309c22fe0297031a9791de4fd2737ea285 Mon Sep 17 00:00:00 2001 From: Ciara Stacke Date: Tue, 29 Aug 2023 10:29:38 +0100 Subject: [PATCH 4/5] Update architecture diagram --- docs/architecture.md | 24 ++++++++++++++---------- docs/images/nkg-pod.png | Bin 115292 -> 125453 bytes 2 files changed, 14 insertions(+), 10 deletions(-) diff --git a/docs/architecture.md b/docs/architecture.md index 3eb383d8fe..8164d25e66 100644 --- a/docs/architecture.md +++ b/docs/architecture.md @@ -96,33 +96,37 @@ parentheses. To enhance readability, the suffix "process" has been omitted from 1. (HTTPS) *NKG* reads the *Kubernetes API* to get the latest versions of the resources in the cluster and writes to the API to update the handled resources' statuses and emit events. -2. (File I/O) +2. (HTTP) *Prometheus* fetches the `controller-runtime` and NGINX metrics via an HTTP endpoint that *NKG* exposes. + The default is :9113/metrics. Note: Prometheus is not required by NKG, the endpoint can be turned off. +3. (File I/O) - Write: *NKG* generates NGINX *configuration* based on the cluster resources and writes them as `.conf` files to the mounted `nginx-conf` volume, located at `/etc/nginx/conf.d`. It also writes *TLS certificates* and *keys* from [TLS Secrets][secrets] referenced in the accepted Gateway resource to the `nginx-secrets` volume at the path `/etc/nginx/secrets`. - Read: *NKG* reads the PID file `nginx.pid` from the `nginx-run` volume, located at `/var/run/nginx`. *NKG* extracts the PID of the nginx process from this file in order to send reload signals to *NGINX master*. -3. (File I/O) *NKG* writes logs to its *stdout* and *stderr*, which are collected by the container runtime. -4. (Signal) To reload NGINX, *NKG* sends the [reload signal][reload] to the **NGINX master**. -5. (File I/O) +4. (File I/O) *NKG* writes logs to its *stdout* and *stderr*, which are collected by the container runtime. +5. (HTTP) *NKG* fetches the NGINX metrics via the unix:/var/lib/nginx/nginx-status.sock UNIX socket and converts it to + *Prometheus* format used in #2. +6. (Signal) To reload NGINX, *NKG* sends the [reload signal][reload] to the **NGINX master**. +7. (File I/O) - Write: The *NGINX master* writes its PID to the `nginx.pid` file stored in the `nginx-run` volume. - Read: The *NGINX master* reads *configuration files* and the *TLS cert and keys* referenced in the configuration when it starts or during a reload. These files, certificates, and keys are stored in the `nginx-conf` and `nginx-secrets` volumes that are mounted to both the `nginx-gateway` and `nginx` containers. -6. (File I/O) +8. (File I/O) - Write: The *NGINX master* writes to the auxiliary Unix sockets folder, which is located in the `/var/lib/nginx` directory. - Read: The *NGINX master* reads the `nginx.conf` file from the `/etc/nginx` directory. This [file][conf-file] contains the global and http configuration settings for NGINX. In addition, *NGINX master* reads the NJS modules referenced in the configuration when it starts or during a reload. NJS modules are stored in the `/usr/lib/nginx/modules` directory. -7. (File I/O) The *NGINX master* sends logs to its *stdout* and *stderr*, which are collected by the container runtime. -8. (File I/O) An *NGINX worker* writes logs to its *stdout* and *stderr*, which are collected by the container runtime. -9. (Signal) The *NGINX master* controls the [lifecycle of *NGINX workers*][lifecycle] it creates workers with the new +9. (File I/O) The *NGINX master* sends logs to its *stdout* and *stderr*, which are collected by the container runtime. +10. (File I/O) An *NGINX worker* writes logs to its *stdout* and *stderr*, which are collected by the container runtime. +11. (Signal) The *NGINX master* controls the [lifecycle of *NGINX workers*][lifecycle] it creates workers with the new configuration and shutdowns workers with the old configuration. -10. (HTTP,HTTPS) A *client* sends traffic to and receives traffic from any of the *NGINX workers* on ports 80 and 443. -11. (HTTP,HTTPS) An *NGINX worker* sends traffic to and receives traffic from the *backends*. +12. (HTTP,HTTPS) A *client* sends traffic to and receives traffic from any of the *NGINX workers* on ports 80 and 443. +13. (HTTP,HTTPS) An *NGINX worker* sends traffic to and receives traffic from the *backends*. [controller]: https://kubernetes.io/docs/concepts/architecture/controller/ diff --git a/docs/images/nkg-pod.png b/docs/images/nkg-pod.png index 5f5804548017285d33b812a84d02b47869113b3f..7af069f20167eda9536b6cdc48904c343b0133ef 100644 GIT binary patch literal 125453 zcmeFZXH-*Z)HWRZ43096q9ce{Km`PBfOHiBBLYg5ZUdwQPzXp1He@V-Mgi$c3q48; zgc1}L>C#JpfJhA?Kp>$d`Sww#Jip)X$NR4JWERUIkaO;H-+N#C+IwG{hv)TmHV6m{ zpirm{=rgAcQK)qzDAekiU)I7q&M|{8;h$Ys&lu{VP`>+6sN45Zs6}||_9zO4J%mDy zUqYdj;di#V$C59o!VlJ7(bYMP;v@gPDkD6HcYbw0WA1@M{TYLNtw3Y%y?{5@d7|~S z){Xok`s+qHHzC)Pa77gQ^hx7e-4nfjRxhx9{ArHp)?CST)#6VKcgr99xcN$^=iaZ@C11-TBKiuVf}4Bl&R~qpberpp(Dxsuo_>(H=P%)#Usj&= z3Jk2Xq1nG2NDjTX=&Qa{J+?SBfiB!*?_*1A{I5y;pPEG4 z>*Zztp>N;Pii$d0Qcx(_%~)0Izqc1vRP^Za;{v`+3kv0TpY`_|tS-;6 zSVG&jIrO=8zIpw=!uR7Np?%j1-}@|at=BY;G{m*cPY;I2#%5JioRAO~Hzw=(utpjq z#o@~1DUmjYr%#_QAlCE9Qh$hwX75k%Z?+Odp$b+EAc5xl%dE&e&)#uyc5K_w#hkkf zGw%WyFxsIz(znW3jD8YvYkjR5Jj)=_#`7B0jkL8N>@$d;nEBIW`%(KRi*xk-Xl0+7 zNXGBP5s>1>U&v_U6r-o|8SrPI1JdqM~lsnVf1Wb!%a`+N z+}Rd3)EN z^TfNb%FX0Q{7#&>tsNqq0!Gr7?lEoub%THaUVLb1NJ;hSA=jSc^|4Aucue_HXXnMd z-oY@996|N@ih<)|{!@3>{`TjkooD_E2{E~OGk0g;@{N?_WUGAN6)3ZH|Hj=M_Zv5E z;9Xw(>g$JAlAk_(D#alQ4%2+;*=I*?&`P|C;_2{kJ4^aPL=?~B_w3!PH<}O~?W8?h zRaNEOOU6bYzmZsoq1vBXj5_KN&0hTY@#DVFVqg`f*%m`@0&HyJt8xTU?mm0|3FiF* z+u#Vn7tr{4pW!Is0utP?^8NcQn>Jk-V}otjQ+2b8iY~6-CTo1^)Ln7MirXvfdmjl& zi+90YVaLAoRaNP1-mia*YQC4BO_6YHO}j8NJ$;y}!S1{ox!jFHMN%Gj>_u4D_gAY0 zr`J0H>^S+!lix5sMHdbqKHS#b=rk4|8A*V*WUPwLgB@kuq|la!6=fs6Cpw#kW=2P^ z>m{g{b$75DRG8PPg&2G?K*Uk0zCT1nGW*K>VmJ#63;1LOOm~s04Hzl@`Ex9L!W?}h zu*CQCtK0_QImY*&{cHGZ!1cdd5Z!hOw;UUOSdwK>aFc=wDPj|jO;^H zCpV_-_U+pd7`SpJ@z>$Kd-n>#9q->?trvT|>GDoL=NNbtxM!Yyy?FI%p1HX>J{gQU zlB%PlQ!)pP(rl-8!>XUp?jHWj`t?Shp80=l-YoCjp5+u`oS@>JBQCjT }Qo-{2l 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 literal 115292 zcmeFZc~p~E7dIMfEp09G_N{_|NUaD?fQo>OsjpQV5wM~nAVft#WQY)ENP@LWDRw`t_Qzji@9E7$34zyNKYaDykN#Hz|CPXh zCGcMf{8s}1mB4=`@Lvi1R|5b0C9rbFt@h@Xg2F;4H#cT)4x;oyz)0_gwHUSKq)R|R z!0SX^vfj)

vdQc7RvrlzX~;RkBpE)MJ(BM=wd}(X|Y@p2R7>SoXvC>jXQZfBj4@ z!;jLGZWGv(VG%i%=CioEM9VvwxSfF$k5&i=-SUpbZSs@*t07l!R>;7jk00n*HRo|l zitUV>4tu`7-~Q&|PLj?}#NMP&akJ~&mv=UrT>bm^5AvZhPm<~_L9>kiL#^QkmMRUi zx68fk>hT`yrLNQIhxh1Mg>_B8%XW_J>L_WJ&g!As9_TD(>&kb_r9!uHAHS7L-I|B4 z{oJe&QZ#7m5q`(URM#F=`%ifD>=OyD2J{h@3smZQz}+zSA#C@?%AeC-`j(Q`>sr`|Oj6JqO#iCE?}L93WRH z!r;Yr1J0luraN}s`m;_>N$+39QG~8TqYdGX^b+^JDnI%%mu?KC+1+kH&iLay19hib zrKpA)AX*(B9zN&n?9+O0i(d#8{KM2%J+?#tWAYKJ`XepN1}kFt7@&;mr=N;-hCHI@ zs_LY(g(TI6q-)^VS`Sa{JaPYe^{XiGP(9Co$qt^)&zs^Pm65ihvc%#fAGq0-#G8ka(@)}p z`E{JBKMb;V|0=LEs(Y5|+EiU#{bie@jj(?toQ?Bpqxbh$4lS)K#ed5FF0bze$Cwe$ zibN5yJr+L2xn`KHVdB|=eNbU17l1kJc_9C5U~q71*pJc;R69xU)m_znqETQ>s97so z9FW}S?*oP_+v_-4Zrhw^<1P!6_|iAvwT+#?Dnj8uosr^RBG9;mApFPJNXql#o_XNBb(5c4ZCEJBR91qtufupq#)CHDv zB0;O_H4WQmZ$1g0^Jn7zOSPrbEF(?Zn20abwqI&Q127?80|F0Rj9UN2H*cPyk`{Zc z1bV0iTJEp1^P#ot&qzWd*29goeBlkXi$+i^=?R@OQa&3S&^&PYM}C8#`BM03C~9{7 zJg}0((J_0zH?j|CZthAwxD&!d>Os$YrO`n8@TMmcw`XE$HZ}h4^Sx`vnnY)YF$0pG zeff^llS$H>VO01ewW$H4Z?e@z7@my#q;jzkcy=7Sdkw5wx7=$-f1WMv*he`{geH}j z6?Fr`M@HzNOC7(So1VdH^r2;?9rQe*ZtO8KAq2W}Nu+omr)xC06|KGV_F zYj;#tRT;`_@2p$@g&s<=%0ZgfQ8)jsrgeBXs=Uv^Y8T48CxbDuu+QNZw&dv*q4|_#o zor-BdmZUqO$49?Ch-CGjD|J-G7$83{mA1>;O%^R@^fREj}K-`t-{xs-zp^ z4WPwKX52XcQm-9oCHA$Z&tc7f!DW3if=+zI-o))TgIp8Bj2-$E5onq|MEqZ{z@->9 zE%&ZLv&qe|7QObshPewF(K9(I>M!u2p+c<<62v(pzkie@@bBNh)im=Tingo)o03Rq zge+j+KE2OSbsz5SgBGVQ69a|4zs=$h04=C-_hjE_9?~=M>DkXs=L45v1h&Zo2*ede zHiXT&7NKo{Gr5G9Oj^vhtT%~Tp8k+pL9?~e#$3|Hu9*#fdHS8ERhWO2i05+Jiv<8j zzk#~$d5q;p|9pA<+YxCW3WtbcMRJ-re$ZZ>F9jVZN*(xCg2oDe<=ZF6Ou~3W-{{&} z1DACAEZg1v>p$YY(If&uG8T`9v!m1+?0_vj2LGl^I~d;?ZHf|h0706BOusE3rz+(F z4bOAH8c|95InERhsD+CFZ-wjgHDlFSN(m@IEhHuzeYU1%L!|)hp<4weZ*P}E1b`3h z@_>6oSaI#}x{K7$KWZZaaZb-Eea-d|h%*oWr>mcU7=hS=`s5H1KOX=0#}oMf#YcU| zlZ_D1zX=TuO|!sy1M6_D-wZ_;d+%MDXWKH5VRHWbc|-TFTjD^m?qW`Tef=eDw`tmu zpsRK%Ycf7lCS9IMY7(=oqWN_`;Ntuf;5X8%uC){IZ$0=!yoPb$3@C$w*WO{ELWh89 z>U|rvzUbIzn7>fncSf0Fev-Xe0JC>;tw88MuUPCMHXg>gGO7zp>i5F9Ma0Cg!P_yr zSILCcab4y0nIB?RX+V9k+~OK_fy!L?f!Pj$>LSRG(F9gI-G009=uKLz3KqkTm?>G+bRR9SQUao=za|z>7lbnWDXC< zF>-hN=Y!^#X-)BT;E@Anf)TcxKWF{8)6~?ol{*(LKKR&TZO;g8y<6s`r%3+8)j4(_ zuf*#Aw+{OMRRX=Q4c!qfaqrj)QBC7w$3B;8e;25>r5^ret?D!V`A%lTZ^X~(DpbeM z5V~P_^5>V`zl{L8Nsx4+7Yosfy%j#RHTAXqmleO#Qv}d7gg;W3V<$N?FVjQJ|1vH{ zAy~$@%v&rMXA3D){04pxTCtdtY_tI}wtnfuM&qeg4UaBo$CVql!hFZ75Q{C{f+R%C z$%kx%brBGLxGleK*cjZGU~W3hs&3n4=&prmv8;*t#Xi|Ms?eV~8a|rY=YTXM`In>Y zQk);A%W&nKyc++RUIb#W?heMVn~7<5s)ma;I)8?V4ZZyGx39be4ZLQwrGE`pk!bom zB33P*N{KKhxXimw*+!v>1cz4nBtaf*mvZ6Z1qE)g;x;nVQOpgrw?m8_4&gosOFeGm2J%prbMbwZ&(WZBWBwJ;|~A46)J@Q;!yxi{U{90OerinX@9Y zBSs741{LpK>-x*`19V)nJLd_ktu+`0!y}S?xd@A~x|sg4ytH z8)TE$0t?8k$PgZ1e*vy7*=QX&HSr$~?(uXirw5qpUe`Fsz`@>K2t>@7Ww;-@Q3Oui z&knkR7THHgSn zxvb*~K7Hc;)*Zau9}GPjk9f8{=mz0@Il$*+BcG~IAtz9}L*e`pfY?vpi9DL3yZ|Qq z&Mf}r0%C+n%w0(~%#C>|2LI`s|nP z7{~0mt)gaBZJ%-EU}uUkSTKFpr{)k)Z(x010u@!Q{@z_LqRTE7@fFcOt);vtzilh5p)0*q3<8=y{E*kUb!{9_yBvMq=^6!rVeN1{S?K z>C?5nWmq3tCuzy=tg~~?@Oa98*K~6Z{aX9e9Q!~57T>*>Mky@x3%Qif8pv!g^PImT ziq~cRN%_WNr=!hc95DBbc9bTO>q0$%dCP|Ui_n)aYcLB63PJ7%HwUA(A2+y22Ujau zMeeqP1t1*xPt0~iOMN)s+2}N}lKa*yg>AMMe9?Zpn3qK36zGno_VpllMDwZ9*>XE| z!|t7Gwps1p2!812m(pE~HQk77m0i|-!^=)Xb3&9tUzhW0oT^>$L~zaOoc8SK?< zcXes@k4)YlWk3qQ!RGm>#Dsjryjbz16IpsL*C8`q59Y6;5iBj)C?5r5zvn-bLZ%;i z8rSV?^9Vj^m$G;(GCVSXe?&0UxX2T@)o(tl8%Bwzd2-#6DezNdd9S&v^dTZv_05Mn zc8hOrJ2vKFq13<4OXz5-v3^un!O5W+HDOm$)OuQQG6Phujk%4OwRq-4hFQTc8shYN zMY$XOxm)8inb~OYs^&=zj@dv{Qw(Eqm42MAk9vR{pT4)TAxUcdLx$|}#w8Ico<$FR zU?qQkDQf9BLs(%|v%GWN{I{Y%9Alp5*j?NSyOMi*PnBl&7q9DCw(~d(ZUec)C^v4)i8|j?lJ-VQZ;J z7eSI3$tm8zh@#VWp*+a8rp8E9vj8(cGAmj)qq_ma0C2}NH z&zX$p2cc#gt{}m4vD`h}LIy>{*qg-7Of&g4P6&f<5*f`eI;V`h5mek;w~OMCnM#!l zGyR(fsuN}<(eCcv_ECpX_p}C=>*&uE#PAe)?$m&0tHoT+>bYu0=$Ya0QA=&p)X#!m zJB=@P^yd+ut@zAX*d;fcA~$;ApA50_osKz9i8_n<&Fi&sMwvCt{C6oEE|_k&&vb6M z_KUi4Dk-urtNSS(ZO`$r%HeLpb@mjym+xNkC?bo3nd@YaZTdPwDXZ4qzAFra_BLdh zFTYKxJF9Vf9?!#KmNMAUjo<*Kg$h z$c$7)Q)lAq+sW_mDj$?wY_?wV$jC7FmhU0kIOJI%{J-2}9m2lfq%0e`*&1M>{9r;~ zX*@fG8+#&C*BRKy1&4UTBlIZH=DnmU_I?btZg*yV$ffbFEWp=0l1HubfKqmrI4$baB z&6RU@2kZ;QIT93;){+Jkqi8gj!TF13%KVmk?Oku<3UB#``|R>)j(>%Gkl|b7m@*nJ zDW8lKwS%J3dJ)6aB#(yb{a!l-A2&#{^YaD^Wcnv~0+S^wC^W7}rtNYaV zZTaryr9%U;_7YcHNFVC8ml9;Y+v{@iO;m_8x_$%t zoykT<)sH_D^j3G*44XBHE%Y2&qP`P!DKE&!JMTrD22;1r``mEl+@J4}&BgnF&p0CO zXgt7oo*DF^e~=bdmRg;_$Bc;7+AgBQLdgNxvOMPk?LrR<(N{ckkXXoXCzqP1#4Ak!|>0 z17EPJ?9?Z-Hahwr_O=lZA*0DR0~tOmFKeSa@n2}og6;DNvv*ooO87pUb|&6cRMFSZ zDO2vz*nCTzR3qPSd|!5+VPhw7-Y(lU$j zJmNi3ul*N;?e!g=%xd<2qz-N&x}eyZ9DoIA%^BP$=pf()1u;qv+haVoK0wyJNHDgx z$nKG#N~G@+7(sNF?|^i?4#0epUS1~QKS|tsl#YIs@kIGXihrei#pHp}#v9z(+2ENC zNLnQ)H$}(!>wGok;tLDj%I)|$sIBLb^#|L?K_OYVSxNblzO9+XoMmPA9p{V`2X{;L zw&aoM&SNN|9i|!BUgarwclRFIYO>F@44FeBRx(Uw$lP1Eh?qLuno0_VZW~+Gdq1I8TlL{_^ak0ZXZD7n|?9Z-cX zlE`1dy6oBs@Lzq$tU6PKB3ehvXhc0LRmD|@+F82AOnuPWvroAVs1#6|=HozFlO_Oa zmZVpqZ!>uP8|Zv~tF!t>tA3Ui$}bvORBkeU%^R}gze!OpvEc5zfT`VA3-{(*;hTp2zVNRZRLtCBNjG1z2qs8zwl;5%1J-*whQ6x@3qojF`fJ3g#7b_uC45 z?dz&_2(B}T&6>k{7Ena15{Xxmp9iH#Iw0M36U1ADCdWHX${n|ROO7$SGHr~LUL)PA zF`+tareMeS#Fk*zqA83~x-u=&X%KGH;+#hBY3M z&iI8_+V?z_oCk67Z|g&NIp*kdMFDt$q1t4QhL2f&Td_0iaU`|?J1jAnxQkZq*SI9= zzIsChfm@G(RgPkpQVDnYDXf@ZVB~R7J<)pQCw1dXL_Ra5lg3|Ny9#|zkf1ko@NX{- zkF@GJ^Ue(^I1~B^A+o1#`u>NCR12I#&MU zO&q6dtV0v^^MV39d=jlp0GesHhK3;*pXmv2dCw7#w+5|`BmeT-%e9b$KCtC|5bp8_ zK7n78D@?JBWxIQjj#H@VS! z(#IcM$+K1mRLE|+6G#BZFm3^XN&VJ1sIT`=a1>r$ zT;M)i=6Z*Q(u?9K!FN6O#C{`}i=T^gWMZJi+aliyTWRdTIQ*`YiZQ94Ftc|bJ*l7I zd)XczmR>P7snLr~lvewkdpR@Z>8G^+Fx_i&r43knJ{#IK}jS0MhnlwY55%~am;jLQW9_Mvc5BRu`#(Ceh{ zXtsgH+})u+CpOOhx-D$=h3`Q9`D%8Vk3y*Z3S@g%jnUQCohgRK51PixG3sq$v%Lpl zI&xJiRw@|N`T{IVjr!0=%(emc#K5;@X-ZqA#z=>(16~QU83zL{tmQ9R%7Lf1n_z4| z@l~8Ut<20Xp8#A%kH|`Nx^S?#H@w9`62hKKdRDYiZZ7UOF6{S7VOfOt(>wXm?e=VA zZSv!)0IG|FvgZ$r`L{Sy=3X6y*=88z4;Dfk{pIJTP_|8y-V!>hdFaCI@1s{Jx3%0s zej;+^%ECsUU>LH*svAiF9Q06SxglqD|4RAK`vvpWBj24wr$O8X%16EMp53KX{WqzA z`o8+?Wog-kfZ!Hi4fPiR$4CKXlgjN42M8`JQ?mj&)#(z(>N5L;Ov~YlJmn4s9_>?; zy3N-NggR_^!esfZ@@27<<`j?1IS|ueqjsA3!%sG2l^eD1^ngIh;4La{b`02;bAEkbbI<|D)7%k-p|8h*Iju zv^}W#-#A0X+?S%y2FRW6k+7fZb8T;L7t@u=)& z!5QDCg}e1aMrak<41sX%3Ch!b{LD5r!z!A!H_^R*B~uT@DRDborv%6}m48z4c7iN^ z3J&ewrb#9~NbH*FcK-b1+lh*l5AxWiaCdIWGRUeQ4fMVR$Jo{FSpt9Hah3ze+1hM0 zs+CAncf%h-rR$78rm%%hZt86m)DS@$?$9;EwkUfSY9{D!j*x?7Zg9Fz4FuRHoZg6; z*$VL(k~&Y@B<$rjDZOYX+G=i$7Cg_X3=BV3Ncy)f!c1=vR1hvV4PRwCnm15{-gDXk z%;ltnhF`S4$N>I?z5DyXQ?LH2sqM)N-{a;}|Go^ySJshC$0ZPK<^b1yoPHApaLL}` zmYiXX+ZixiZ9MoWut0Hkh@`hqQC;NEUQJP^x+HDyd^v03r6cewxT3ORA|CCZNKLN4 zr_n=7>b7ODcqiImUpnIyc&?@zsr#{d;rAJVu8{1x6IZ*R}Qy-Smjlr`E+B z6K2wcp3u{2$%~4*X%1NM(T>WK0vbr7+zXd3T$nAuJkS48mf%7-byk@JpfvQCZ23k` zx36fsJr1=VF?6#MnvIq6w@booZESluKDiU4T{SE$*EmOgHzDfPdTZ~(%>UcY!CF?k z>N{%(L!=l{?7A6%ET)ziP%-i19!~^$PfRX>Y-)>?a5nQna@+K}E%|kbR}P}#oZBnU zQ%~^NWMdgqYd{9l2ov8`lQi+{>Iv@el!UCN8s9K9GmNB8u@gtE);M}~^diI-y$My{eZf!r zG9|$|&!G#P6o=q9cgDPPxBPEk?yk@T*NFMr!U-+5#C39)~X_9!Zu43@W{eTF{PQp!G(rEiW zzrJdm83<_CqC^j8=OU!X*Dq`M4L;Bg)X!6iR705^@ft}Ht-+z%;%N1{QlJ0X_;ohwA2mG||hT!{Af^-teO&~`9jRm*4BFW{4&C~H;^EYyeF(qlD33ZIEMKy=WRZlG8o~p=sj-wgbm;&JD`G$dwK+;bTZyg zs;+-8W%zjp^z7R(6kmXD2V%^HpvDRD)taA0IvT!ieqTQbOGYT%87jM7c_D0+?r|M2 zZ-eEdXZTTmZ^+b|6+D>J^U@L9<8ED6bP~Gm=e^$I=bCcZbU+HMC7y0?AF03t3pp2Z zQ_Y4O=XE9g6^`rbI}O3+yaS&7-es0(lkfcYg^BGZbW&h!$ zlkyCIWAUz^AB6|piTXN$QpWNj~W_a)j-$ zK(R@OsUb@*z`U*`C|I@Cet%FLd@UEkbcUzgG{`RMe^OU?Qf{+RXoWIpu~HbOh8X%6 zj8uod=N+zXUJC7?2zGDO13{%*(T*nDMw{>pjQUX$uG}unidTpto-Ap;oXE^cw36M1hmx zPpuPS)kZJqiqwWEL(X6OLbT7d2__Jq;poNj@|?gAMohsa^?qtYV|8k7<8t#8P_ZMy zVg-h3whyjTK1}~ zeQqBml6BMnlwTlapXzOy#Ms<}yZ{o&WCM)MCENIO1mZD3l0+zeu2nuo;*~9jb}?+x zW`N>1O+Fa`xkFhzPFDWqs6(5Iksj!~jUq0;B z%C$FVK8tvL*Y7rcU|@2Atyl_|-7$?HY;Up?DN<~>ZBq+Aq}BhlBsRAGPtUQ$9=JG!*8tA8$2M`~hds=>M|YN{CK9PlR!g}y zB&ZmJyWGDnwbOZ#V_F?ARfOvZdbxLBh^p6%y5R%*CXSFDY{K5;k}wZB+v^QY$oRGL z((o=F7zZqNR8SpjbYv+Tq;gw=|8`L6dKcN$T8$fAS(>e2KZyjH@jc&nVv7Yg6cHu9 z!jb&D-AWsWXud`1XbNN{PqiGrPxk4+QRyc0^A!2P_LFdTb|8;1rF&C&{n z+>zp7^8>7CDzR;^P()?)`}S7TQ*A8Z4>Xk|HU~{TXl=TY)uTgSE#FGp>3C5dY*lzx zOQv!%vE4^)>z^g$;X@7hFpge3Z~=!zind-%B5guEu0O?c+kOgIRUgPjpu2z-R?857 zYESNWx}~&|){4v(31(v6ST}>Fx;+(Wc`(T8y@s)UebuA6$4|a-@abW z`cJ^Ws1DiF;`%SpIx0On1fu^#JT^XEMKRt5lgbcoASlF3QcO-xz3#I`Z>uS>#*gQ; zo|{sob6L*|_NtJhefbhGW%8lliJYY{t71{JD%bJs1tlmCrMfBD?@@}nsc_H*h@Y>x z;uB1&)(M_CZhj2}QIijr9<1q>#%uXrm{Yhsm&|WrqlhqlfIW~0O%o4B!ry6nc{=wN z(@Gd~Zz+!gn9mCe_V;_#Y1dUg2tTXKGwTO6fX$i1IhLoy7SkEJoCKG?dk?se>5o{T zORsB{)KQ+PhtCZh==JLPKpFig8(^sv2tc|^Z$qM|J`%~qxwjYc9t9$&gO z?(CZpu<*5-SIz0bEZt))o?M%DL3ZUyH=PzP?}4>cSjHKgsGk=M;0=^+!~TQKwr9{Y zER;OzgWn;XHKO#2-`4BqoMk~qDsB6L?_p67#9?%Q#9DRU?>c28fI|yG9Q)1heJ4zZ z&A|yDnyZ`fr9TNch>LWBwLS|$A-fx#{@`_+d6>#>EMV{cY~-%k7UY^-x*_H!&&p0o zbfYxxgMG#4So~R@ANaaLaL0fuD3#RqC3gJXrmsPOfi|yB$%i?r3Aj%%_i^|nsEzLB zTPzlA>@5(sVLP7q_`qHO_?ZOlyOIi;=fru9i8i*v7e(>G6po%&AwbhD?C||en*q8EcDh)`Ml^fzSid$=8!UH>r^cmoveaM zW+Z3Myw{h+@&(}@?C*qUg!>aG9%<_uK8T)Vunkb}ZjJU=Pu;lD4X)`pTxT_NV(s8qZZv5Arn3E(itF!>-oRQB!h-If|$gK78=xwxGXd^{kWjuh<6B_^3{v z@=mj%`@a!}&nxkvPC9RQfex_YAf7+q!}LBj3@A>G@~NlisM09d&DCokY^tYJ$FG3E zDcAc2b7m-Vsl27O5_evFnwX#D@dnM#H;jJJiw&rFBTDm!Nm|_V3Ce;S#f61- z!osDcVcu+G#j-KuYNw+&X|BeI zq~#$5as7@|tMEX;Yj}4(n&Qz^-mXt78mLk?x|9ki=BB9L8Vnn73>$NF)mRmKoN^}s z)%JAx6(uHl6D$G68!>VEzWREwq@uOKKj&XJL8dLttQf5^6d7ii8=&Nm26lnoQSL7X z82#1f2P*6HJG8@al%C;1s=lfDmj6@(&|(;kg4|@5-X3^UaNc(od$F%<{{To;UeRks zdTFLJ?*K}tf+$X86ITTLQ0~>TE-l}^XrD)K*N}4r1t4MoBKjmiffZM@U&o_8$H!D-4y zy%9I&R8g;_$mo%@I1Tl+uA$iYYLQb5RwKoS4=pZFes z0Y1;*uYgDrtNI_{gRsE$On^>S*G~HV4)C*g@T9{m{kjL~0XMlw37a1vcJ)0zK()1r zWYQKvRc4C--qvsA&L*%nw{N5l+sOjF;OB5%I9D92dScIE{Gx~qa`fY{7YEzcGh&Hn z#ayi1wZ2geC+9lRY($PSL*!!+K&`y_LJ3y#kARf_51}bW?ySDUQ$Kb>vS;a0h-(@iOzXN)($gR~$-%Z<=ALKuQ|8F{n08Bjz(sr+%{cb}-XXTJSkj-@3o{u2i&_Fi8dmIIhuLu=iKH8K1@8ZlpE zU$vayQDy@?)cno|9&^@V-&OTLG+} z!HzcDG8bD$G(AMoWZdIp2MQgB-+Gt_y6sWk8J%^JnqnOnJZuQpJ2g!=%y!{@Hwf;=7%E>Uv zEH!OvjX!1fFHp+{t;M++c5)MPb^aCh?NODS^Mw}xgRp3jxXW&_Wxd)p-cT6;KmVl4pHY5a7il}*=KT8Kf8@BP7`hGi=EUgDz}=I;?kPO^Q5BsvUe+Qcafw;c zm<9ZTpGmo-+NwIl1>RY}1R2{fuerE-c&}`(25lM6U%fS08L{wTb;1CNA_8Krt)Zo@ z-_vtkI2SWm>{b(Ep=+`Bs1mN*Kr5F&+Q8-IUIhUfoS1<;Wa6_x3Hl@1Ha7IbLYppn zQo+PfZET{J-y{-NJ+Bx+axG&1)-+hoE(Ia51ODP(i)=2<_*q|GIE-qL-q(G_#m%#t936+rSNUMtQ!ZJY@Plp4yT!6eOOaSf{jz}8Z` zBmR(keTZ*)G6>du80B8A5>+nyN}LX;Dh=?OK#O}3Fs)22JnZ+37EavG+OEj{@slwj z4*P;SxhGgrqh9|ug-fnS3blW8&wN{HNg>{rIqnS4pqUW2ERM5Vd}!3Xip-2 z(*UUxav|LS)x4Zzyrr+ypdHXSmx?jCePI3e-@f`zEA%`q&BTDcI%OU|2f3x+7C5FJ zc=CJ!3?^ZL3Oxe5O1ZNL+@*5~RUuuABIxdo5kc>SiY5V$vXx|ulV0mItmzWc(d3i5 zxXPjnEUPt#Gk+^OK*X(6=Eg0hXN z;XAV1YPPB1{CA-ixoBnm5WRF?0|>t0b7r?RyiXsc*@!PO`uRX4i8EdFgP)!#s-j-M zM#*zds8-u{q%_Cw_W5*kj7N4)o(vOp#2~}mnmkkqNS`W*`Q{if`O}f?Hb{6VP$R4y zBTfuBqq{RKu))jkPMXhVIh_4`6wIr1k}%CK{sh3G)pnnpLy54E%NIBj%fV01b|(jvR=|GVyVMbEohwnn!M426IFY zC&*5JP)0^aGR_`wcjZRgyT>em&PndeNg@EQE!+r7z7Ft02@j%$1ArAm3aEC;#;G=R zYg_V4UqP-i)UHln#0JwrR# z$TS8M0KNdKU26i}i*AoTI@=~pcdfksi&Qj6%6H0}(q^xm2y9$|sm5fZuYh}>8Lk2}9YE=Ct?uP+w~3knt2u!2z4)1WQhIM= zKSK@-y=0&X0&|QYnr#Q3sQmi7r*MSJOJ>fvmZT?q5dlWKdO?unt!#A8X^}ze&BlSb z9FNI5;9nh-3OTl8Pu@gH1OF62l_WiY)Sa@`bGrep3!t-ZsyUjn#{fKmD-;|8ZZ2NV&A&1~2l zzq;~`w%L9#z3QEf1M27iJUN`T)oTX=@~FNb22^q9#w;WOpS=XOm;na2fLr6+Ae9%~ z0v_wRls{V##N^};Yr6tB2PUxDyT8GV)`#NfZ|iQRy{O*-q7l%j{<~n1ef!i~FrM~7 z*l4lDZhH(avVgO#xcuT*P&oE_@#_W`ut2UoDS4xDW9gTrYL?S~=?T$_eTMdjgFgJN zC)}~JvM>(euyFcn;MQ3Y(EN)^S(gcIe@PvTR~A#Kr->P1!@k{v(51&Lk=Un+Fp6mh zzW&}EbWy|!U@H4I)__nc851+EEde9QnGj9|k^ZO9Au%A@s;DS#g*upTjJT-B!y5o0JUG zo0DxsLpy;E)s6kSF&J1+iv4;Pm>6H>`5-$p!&zw>9uYg>1H)|rBiRSX)`KnqG$a*s zfiW3*0GGA{IyYcxDIj062GhvlFxU9uqAdvf%DE*C-YM>&!FH(~ndgFeUKdROcGii( zFOjUlL<4lZ5EI}oRCGelfXnP_Ky0mAQ#qDkDe)>8%j^Np^pHRKi27#?OfAR zFhrL49E|9SZOBZp<&5BtJrFvy=D0vnlbB2}|2!djoakEuQvU*dF${S@oawiGx^Q+S zkk11D?#`n3i@=*OYzBvfyC7?9L_&@W0x`Ce^QjhuB7y=XF7wh7XlJGYdJXYfn|pK~ z;9I&%53(!rwo8r?pLue+E94Js;^$zs(yyXWJAnPRIFS~8tO|4|_oGEMfE3^hNayGM z!7zk9s1M5QmpZ!Wwui>owZxG>reZ5U!?}SInM+A}?eEdHwf=0U#MK>6Sqe|$MC=vW z;jcqsBnz1Sn_q;z@&qFbhn?lqul3p?jSQ4xYlmIIu9}3HuVs7k)xn6H%c*eC0do99W~z?|%34ReJv=-4nSd-GjrrFL!m9=O_n)zL z#V3~p`)l2pUZTFMFSL$I#Q4`2lh9vV!0hrYWq?DViO-VU}~um zxVH~)0|wb0YVFEv$b2fJu(y*@TAx3}^ibL%aTU<~DD9Al|M(R(<|b^Lfh{d+Z5X7l zu1x(9u|Lf!+5^;Qoj>n{y?r}1mnY}Aph)K?Fm+<=C3@G^NwLepivH$}w=KatUcp-$>DEVJ^eIM5FK#6!) zzJPCJFS#^(f3DfSru@f-Cs=Cm6{2+PCKyk!-@XJ0T~iNL$Z+Z+n3f=>ly^o0I`;A1 z!;n6;P&8g1nJ3D}hvJPSJv2z+g-!CAnl_*GZ+bwh)x*q7SOD;IS3cS?v?j;0l{pdAzoZFQx50r8@NPhPUvxm$75l^CO`vX7=kT9NQ_VI#Mx&Dq z4q~**W}VSA$U&SSlS5IUcGWE4*bx_~5?qk{E}EFSyi$Q8u8S79`V0DV#w|6~E`GP~ zLebAe|HiVPzrKiErEG-SKL2n*7W7>_J%`UH_HKTQ)(k$8#Hj|2BD57}B}Cqze0-&; z92g3eU!Aa{;SlWh^Ov*JGkayAglX&{kQ+yxqM#_CQ7Vj z6HAfPC2Vg{GKCW!Co(6fEALfdqv~lz6u4M7VTH6itNTVkc=K0ziwGE6-TQk?*fX$D z+|LF|c{{x*T+wKLj}9t$`v-q>AO^Z&7}sy`K-JzTw--P0q76H=Ana>P$qk~4ljGnw zXTb5Ta?S6WTNI1!jC;BWO8*d8?+0IT0PL8lzbg{=ZN$;NPZK9VSHSyk-|TzFW^nf8 zal%PoG-yIC^}W;3@LYy+`Ii#*oNhnZHsZf>2_%*N;RLWm@?119<{o(m14Vr3?0)97 zHd-1P11`N@oefU|f``pC$oKIviyL10?B>K|qY0h^u9^`E-|^}1P1qjNcT6QdvppBM^@0ahIaxS&xOpO1kawPY!Rsi-DN4}jz7Qp{ zqdbFEPU}E`W*QU|#~0Z>5ZH?%?s80EOWEK(NO zUE%a~$F&X(>K+0MEN2UoI6>e?9Dz+i`$0D_+Mp*qDoVe8#Aa2W6mYgt!KVWU_LL0l z8iE|CqPsOKmoRxC7y>+;y5(QVDel?txo0`6!w*pHwko)i2!2{0XR~J$z|g1FXXlZj zy&I2*hn-cn#(}2IZioOzwLB8{ntYDPq$s=?*g;Sgcv@k!$9wbc?jLVL#&6~>g0D!z zitp9fc}naG&f{P*(91unnj>jujAshA5)54%h)1xFpuXJ*|3brhl}%kJgUm-Do-fX^ z`+V=n2`~Z+Uo9#*o4rNsLNr5Unsy=DK99wh<{Pzg8OBY$yr2LkCi#|3WXwW`y?-p} z_|s%D8>2kzDIn~JOinAjbjetQ;s}~mP{X!xAiwKs{oGwRJ_1R@@Hs$;+D}(S!}cuX z9ve{u&NbiUz18PtE-vdP>490bBV+F6E18Xe{IY^&7YlFQM9tVCRM$^J04=FgF8)xN z34~jK&Llsx{mp0t6;k&DSA?{Cf8sxQCM`kz(@p}k4t3A7Ur&&a9-}i>&0_qQro38f}HxQGxt377{N=a`$(!KZOSQeYZDyhTIKcV zZlOgEBnIv$^=@ZTV27cgu;dhorTakJHUs>H6$uQf_PbRV<=Cy?`zP!=K&SlVO6*7- zS4wiIdA~da=5tCrJRJd%Zh5vMKmiHgr9q$@9M9)LksRC-@oLNzrJq0m!$vYr2xoxO zV=Q{SE%N1)e<-(*D*K%->C)#t@R+#XM)nm=ZMF@MLvbmPo7eqd6bwd~TXoBzLw;U( zDKXH4Fu$>L!ALVAPxF#wJiQ>tHsl2 z=PdzQx!jawcj`*eF;)6K*fIN1k6L`q#cZKy-yO0qwrB>R{==UF@P;YA8O(KL`=1iu z9i6ndc~#+PLx$sckTVaQX5D*@FSTqPUmb`Fc>V0!w1yZCn)m=u3g<^%s}vCn8)CB^ ztPi6WK{Rx4+^#R0!UO2vT|#fFPIpD(CVe^Dt``~t>#wjg(0vn}hJva$R|3GFLGVsU zG!!KkW z?)VU#Y?1KRtv@8oalS`R07GZy+S8PT>N%x_Qwus-k;51dlTK{s3MF<961v)inIWI5 zlu_YdL8%PU)UE`Evbm3pX_idEY8m|VBVxjpv16b?0PQ12@9;N5S64WQW6S?_zeg?L zC0BM&)+FrZUgKBT3Cc}Nlcan$L{AW??sJQagaf)^UKIbMLTxXBb{O9wQkvLmYUgy( zd>M2W^%AT~NNdvi)Lw^B4A7S%#&b_~B(PUfbhbMKsm(tLD$SH#d z0nP*lb9(LGb7tKOKHKEYub=h1BOx6?VNRuaE2CF$#qr&W=qx}3JpQ~H(CAxjwD7-N z!ASw@#xs4q!X@P>W38X902KwXsp$JGP;kx^4P%ZSolvc_vUBKm8mioqVW7nr8S z5+3#~Cs;N>-JdJm9yzd~kS7YbVY6`djRgpkVDQ&lwlpOXkP`w!M!IGyk{*R0r*weH zu5?r)k_3lV!Km`Z- zGVtoboE0!{g3Y{-+7pWzLfKv>FZw2_@S6N!6tO*W{*MrT{c+1MmbEhUT~%w!79+rG z<=U)x00#(RGU?gYLcK`94c>wb7dZRg6T^@MS7ZAK(rT2etn)DV{%2O9$#!Q^5%@Dr z7E`I7MU$#U$)AAa&F&42N!tl#(94uHG<*7IBl#YS)lL;^UVd>LK1kU`a&rH?50&27vkXeM zY%Ng8;#S`n-3#WdehTVFUyAYUp{{gQ!Yk0d0qMi^;-E0nx9F7LMM}&_9lEZRR|{fg zm-{d`@&T@o-Iuxy?#07_urA&&1%h>&Vztx0T!|cRhc+ z&wmfsrQ*yd_g-u5d)2+Q$|g2y>?07QK(CFuiD21?8;&Xk3+p*D(CynLYN_fq2%XhR zf@PmG;*TRsGx#zuLW`$PSXUi)!ewfSyp-08u#xl+Zjfw^H#O2ympe*|_ z*CY>#67l`rs}uIK&)HWV=2XlNH=Mf7hEu8)>h}Uxpy=4DZRcP79@|!2T{s^o8-kE+ z*<@H#ODkt{hue*FDzZ&hr#Zg!l}0LBnM;e~^)z8}%rtOCs zvB*Q*cS^;?6$LrzqbVjSEE5`zHPfi*8w_?`%yeChO&(V!+!Inf{t?B_hqcAehBr0O zhZfo?_BTM%K5Q-gkWJ^v?LlBzaFegwS+i7aDBd(y5+UaNW4HF=4LOJuJOS1{ASZdc z>lb&nIPb!VOv46@O9#&cw}>t|M$#@&OgyVy7l;nDY>E3i^VV5#>!=+Ec_E>XT$H6v z<=GvEOYTlsT4>vJBtxM!xW<7Lw?SP5_DK<{4UGMV(nqW& zak6-Rr-dJ&AeTMZ+@?%?O)Ha#Cdzb}%uEO*u;Ri4#j{?85TtC#S}hI`J!o@wl{1oq zta@b^vi`!uQO~U*{$)5^|A7m8;$E+y$;eO2Ch@bW>UovD+G&g%4V&O@tHqPoYsC6J z$)u~>7UTD^i3|XDn>x^2MKm`z4*(6|5xXta-;#Gnc=+2tjBDZjCo{l{YkdH%g z+W4M(m~H!x2SJDdQK+$x3ba2B(2)irb%e@d!L?Xw3zw*z(Rb4rBA3klc!TFa><5j$ zJ3sx?3VEfhY2sh!9$9;owT zfUFB~&fy0jCb=xKJAQr2Lt+3(b83Or@=C&I=iVAUhW58hWlKX{aEW|jHkOjkk=s+yjl@z z3NRu{xE%=r!U}Y;FmRYg>OYjRP?DW#6I?T1yN_{KLsB{fl9%U!TF^9mz5JNAEdKc8 z&zs6~L0lkOoidgW{B!TUtI(@daTlgsEYb#Q%@R6gQqY+Py{>xzs@Ct3)CKZ4=;{Pc zNCQZ{!&}QD8oo0T4u5U1py`2~T$->i)v%jjUz_qkFSfyN$CNw|aeM=K=wJwZ`_a$H zg+VK)W$CJ?Im)o&(bzfmJl)RgI5VILnNF1UMg%Z(K(B@Wco$wr41~t;) z%c`V2Xc%5be5UY(A)Vy+FbuN6yqt$l%Ni|&#L{_y+OW;^eJ$b_1%A{w*PNjQCNV9| z;&3B`d_^#g5Y6m65o>-yzO-bT$cordm&$ou@0*1}LdX8*8a?mC2Wxod&i#y%va z0667>uR2=$(JUO&U*S|#RfoW7;rTKbvsSfD0*(wVs_;B=!Mgm2>U%b5T#^^+eUWMW zLxxrge0A19au^Q`Kl$rO@PGhO53ywSy*}fa*v9H=@$-!%!DZ}`><49W!s`KLs_<+z zA334J9&V2`<_!&TF-rLyS9|dzP|L|!PGlqoOR6Y~nV_}-nmZ2#s1M1TsqPh%xWM5A~l6nK|JsZ2~QTyB0UAOd^obK66wcL9U2T+ zAYAYV@WI|yU{6TDTJz*Ps8|@VllIM;B>(8@Xzs~? z12#kS<{M0=R$?0e((?Ae1{7x@!e8!c~AmvLL^vk4OrIt@RFk z5wu0Azr@K;uAn`L5zzpQ72+fH9BB^SRY{&(0)o{LSX57Aw(Vtk|3T6t0LKrRRB=rI z!~DZHfRt1ZLhc2?`=u(n*HMu+N>10t4*(IToC5ocZiw$AP|0i3oPcVo?m|Pms_LU-W=Et;iDLiIJI?91% zrj0^23o+Ju`|zZ06^H5k3pzV$f$|d1Auq9N8*Q_F57Rx{kSl{wRlpOviw(`$;xH=Z zU_Z}lS!7i!M(h08PlM^^`qBv0c!McfwUt1&Nj}>d4%Q8SxanPbiY=v)zi;pJxwy^k zuTIXvX&JSVF2JvgQTSu+0xJ+FBfANal%tAop+&YCCGYpa7z>106!+QyEoQFw!en-n zTn#CJ11&<)60x;ojSmEEA(6@7uChD>B&b_tbvH_}*mcx(fK@CO%%c!!hcs0GApT%P z0gN(U2ex&CyM^d;$;0Y*aTm{EfCKnV4#96`f1yU6#oY+RstcMGy`za73q=h47+&D! zR6aolVL5J7eYu=}0PH6cx6^k+-lGf>#4)t=D{RY#%uIGo$9-9YyMPGp;lX*NCvpL0 zvVYwM(s^PF83%XY7YYpG)&t)VS0W-u_K{dy6d2v76`EKg696Sv139eQ2B__muCzjg z&nNO#hH&HU0zk-I`E>hU1Mdm0aj50FgZE+)7~N7z1O8}~g3N7Q-2`LAgV==FcY(D4MpvRq{D1}1 zfDgNbt2ZRVk2&jKus?q#EOW(QRm(V&h==T2fthyV7Q%;|o$WGp-7rj2*gCY9EcSY+ zIu;|KhIAg^3AA3xMXF^(DT#^3*>12_)I^Ayl2UA;1gA~Hv?C+6jMZI08H)`EYG*;o zS9>rhj8^Klj<`yXX+FLV$Rks3QUKIvo;S3Lj#dX)nBp2HkE18Oq;msaS<6cXC9?n7 zdJL8NUeu@@SWQSxb&=;Qt}jBIQYc`3Al~2Y=|hMN2aAlnESl@9zNnpB)LH`J*(dtn zm{HWzx;vFIb*3GHX>|}-n)$I30?7`6!t~yG)jUi6SasAtN$Oxqy(bCIQ!#Bx=eU=Y>zV-Gw-z< zOL>scWRY0stGnvQf$AYEa{>B%95#`F6qlq4-M-gNFsOs9_B%!~%-Q6Dx8BApHk+y?5MwHBmLKv~%!Z4!vBubdF ztkPVexBwN0!8%S})Pfl?eP@`GmWHYVLRV+H-|&lt*j~_j<5RjTY6LtN&-;k3epoVgZbCmGF`4{x@u%hzN)gk&_P=a ziuZJ}ELtO}OOS!2Viu9HWzZyY<%lCFoimE)g~%O4n}G2E)$g+JLRB+pA>t?)z{?=G z7_d5M3xvA})FPe5@IL(Po;lH@aBsC$_k`Zj&25qo%K&h} zhXQIE0EXjQGE^OLe1~E1bhd|q%dbF1BPlR@LTj&BLniFbg?D^9pGjjmjOVB3<-V!t%zS=AF>(r zSN#EGiq%l|WkbP{AtGCO0?bugLF{^o$}_brgH-Evl+XUjH*7`+m=h7RW*>oIE25PK zmUARDh;49D;WKcESC#CUBC=X$&-J^;fM5)kauWnGD9nb~91@e0t02@v*zpg2tg%qY z71Cq3j9d_jLx-D9UB1C&2CgpElZ^7hZ6&XL?^?{@@K@>05|V?!Pogns(|PqrCHjLr z;5X)|OA7+rVa!b`tFwDxQ!QjO8NJc!3MAUl7AnLD_&g}hwm#~*@JNgwVuMHYg@Eex zhXS4f0xBV-=#G5Z%_EC{v^oO3)&sB{N#jpTP6D62J}|MD=Rk$Qr{hni{z2Y{)g&le z-dLD|!xOaZLWyblbnN(r3tNW(XP=Eb4uWrnj}wg$wHK47#eQiFKk-=~n4ARUB@fu@yQ7)A@{<}n2d@Re5q|8>amK(sbVEI0T9$@(tD zVoscm@spFrBUe?wDR#?e0>BGKjzmVBuTbCL;Ls5D>GXN3>QP%Vi4^w}!3SS05U&mu zFjWCfX01`kd{pj<$}j=5KZuUKBdxvP8O-u506s&Izq=8t1UDNpC_4A(Ic(NpqdKTp zg{kx=w8&`Rp#n$&mQbq*4yb%kYja!oTkd8@C8e+*K^(Xu3f4zOo^HY^16a7|zf8s4FXSf{eV4O7niq29}N`FNMiVrQvVj;^xXGFQ< z2!w~;aq3Ws4XISRh09r#;sP?YdZ-Y9&<%W&!1O#&D@^UGs${HT={%&0QMeZ}3iIj` z;P=-MC)c6$m(}M&dJ!*jy`p`^Lr_o*QJ{l$_1wRl5bYyf>blAj4p^}?%xN^S+_n?S zd!e`)d=5lcZ4ETnhG0d(4V6To=E=CJb`@L?4|Ju1>b}m+3HOn$MJg>DakU`d4V9^V z*?ES4`OSi#ytptFqG}^9crWm^#GDtZA#@!6&-3l^<{i0?;8|3y9VCFKhY(2vr3ki_ zK=(q%KiV`9JpwBI*MjOhRGo+5Va5-8Ks<=QbI*yZ`3+04QOj_3?v5@fjzYIUg}lgF zg!Ki$;7Js@$?UKw6j%yuMs5M3VTLkNL#Vw(SKGFS>Fw|BA)@PI=YmsLj!nhZ8N!*~ z#1jlExq29vOZl*77SSgP@2=%p10Y{ohh6F%lm?fG(;a*CPKmzW`ShCmC#KCW#LjNc z+@W&#$dR1@@YvJuGpm}%RO`ZKYlZ8C53mkJ47q@3ZB(=d&h}Wzal_TjjwI#e!zWIp zRaQ!)QaGOCIs9cwPrW5xP30={n7FvnHTq;8tL6N+Q@%z}QbnY~z>YvsBpE7tyn@xu z)C_eqUM=NjWdW=BJ&^L|BF9-T=ge(iKbr@7KT^nUFr(gbE~XWP zd0}C?%g4k;*D7xF#V3A(ZUwh)H}Y~|R4JFV*hK9gi>wvScX*FSxDd!oPS3gDw8T%U zmt?;!qD3t;;@0ZMdJbe%3O$isD%g7d+lBYq?&&vE$vSn#}mxEmfhs+MQi(-m!h9|4o12MYo6`ydrdgdRsmRAcO(8NWsCw0bgJsy%y zLoNDJ+v)L>uBX?pNl-*=JYV^+ob~(Od{*L3x{5_}TwNX$Ib()#uIbRa!_AXA0X$ER z4jdURhTQ+~IKf}w+EIP*>!^*NAy&34Z24b>q_0CBDI_>U87q7$=8RV zf<*VDXU?COzJLEd_{~z`U8*gMt*sBriA0enJ;#}thWW1s9+wbGzgv@KSZ6o979oO5 zqHOO`4tM)e9W0=A>e8iqfYa)M|8{gvGle!e_GE};IyhFg6w;;GVWXsah=E}!M9@4W z!;S`cD@7H!yeoPBR`X^NkOuw@-Y+ePe|!{*$GA%tA7L_g8=a92ih_a$4A9cML5Bpd z?zY1k!NI|Hd{MA3iVR@c20(Vv&CNfJ?C-n zjeeOewXWi%YisXrpSTa6&3k|USg11XbRgEco^gOZW;oPbJw#}`A44!H7yHeUelf%| zeJ$@gbgz97h)PByrOX^YtZtP6qXXmNE9~?OnMpC_Sh2^Pz++9^CCEF{7HfoX&4J%S6 zTxwztlTZ*Q}5=^<&v%d+Ep~gHx(7fFUfC>`0IQdA67xgN@pM7~@6{xmz>AW2f)#GWcu0r|Ez5Y9w2Vwn-}Acn*@mSgm)wlnlX-k3Zj9DD>(3vhwkKon@hqedC1Q{8$rKw1jdBGuoc@#`BHz zTuY_5G$vaXQ(}1=f4QrDr#aPEzFSp4pIc4jW9n1;3T`&9kks%2JU^}6qa{n;-rqmK z*zL=v!J(sP9Vh>h+F6um-fnEh<3PtaIyl|Iw=d=L#r;)^BOMNwJ>4&S69nOQUkM$($L~lz>$<{m(F|judb_D8q(q8ITnn8ha-xfBq z@+;iSz|{@~0`K3w)46D$2@}Dkkt>Ujm0W~c0Wx@{YRPgBsp=&B@y*H|p9Li(x?6K! zRYE){Rq~qYxLj>*ZJM>o^sBSy&NV=(Y71Ck4?5W9X4q505+>yiB&5mU|9GpzFX<4H zxQ}ACsUoGE#&o+Xr4B1AD?6Qnz`#K0@fh3h;I>|@AKnk~OQGt{gG@|Dwo#LmLUL~b znDKu`2>mMHp_?=hJz#&i^m2L3k0|m%VCOe_n=F%b@MmV4!KeXg06+sHK$Vp>H7!6^?j;bBs_4n{;M3;^(S;&v zYHD~T{T)|rhwmX{2SN81=%yJbRf^k>nq%z9qU=xe1fn3wP}I~9I_CsfLRmrKBb0`p z7Z=ykcA59j%*yf>AQ;w!DEBK|&ZV`bhW5X2sU-=@%gbNMMO_f*>sEn6Ug$|dPh6-) z(hN)Om#N*HbUmLE%^a-@UD~Pa2k}&w2+=b&)`V^f1q*{+A_bP$vg{wQWRmCew9RE1Eyq7^EOe96P2(kh zGXV94nVbB@^XC<;tuviy6XT} zV*a4_De0@Q4S_J0r#%?D&r}^8#g?O>^u2Zhj{h%vV7H%pHUd2c|*TI{W< z!%?!6aW$!j{FihC@U#>Bq+RO|8?2#{+34w$Cr=I^J!-IGk*D|lAO(E*7hOgwjZICk z!N|dWoULtkS>Tz_gFlO&8R|`L-MYnW`b0HHE1NHOlO>LBF4>nPlAo&hl)l(3aX6(C z7RQU2QP>D5ylZH15UrJ(qIP5V?Cf#_xUuTGf%Z6Bf&HYGhZTuuJM=+t5ukxDDK$3H zv?Dk5#7fho?a0@Eyc>J5{xdVyx`hc-*%{`nyVgHlXxnlBid%s)UO!|a>MetAQ4VWS z+@B(7-83JM$sO-GAygDe3F%#X>gvsVm$vp|3o&%qGULUO z$yHS{XwL>{)K8eFl2ut9IwGR;^ILlzq@<+$Cvgj!EFT3;Ga`A$C7;<+#jcEyoGnc1 zS-NCYc$%Z~AH-LzJ+3+quhp80HQ%eiw~xJvwT_$ggC}qFfm7V&;st>`IeroAO6e*u z8{FSJQgiqDeb=)U*SK{na&@TL&czhNB4YjUc|>=yuN)c9RB^R<8WBG0nFg=~7DP&d z&Ipy=xM@g3>8+|!XGiBT_OzCQZh*oF4$lr1FW?I2^M}A--eMd!r|kj2B=}{eRma7f zXYT{@5gOwhpX)Z2>nArYcW>7|3jk)C)t-rMo;2hL0QZpHmTS9@Ffk=S#Kjnrop$s? z2M@k~`?hCv#$6;>)IJUNRBD?#6n@(xjT^<((IR-3i>n18g{`}f8bOzcvJXV0!!yJn z;b2l{TzEQqoY11sg6$^Jj*I>fqF8|xXPECb@z~3H8Y6x8uCl&Vn2NV9;J+^4B(}-n1U-WU@w_e1pyINRm%<=-lEniIG>@+D$$C zj7$^4vPIPlvf5fDs11c)BgE9EAo})YV_2eCgmv;SPkj3jO|-kK7$OtEZK07H-j_=u z*JWlu_YP;B8GodlAJ>U$`G9f_YU@sd{C8mqS7=`s0JEE zgFS<||TomZIQHA+{t|}3+>92=8-@Iue;Hc1z z$s?Sq3z?4P8t`jiUR$x2ElJAIsF=rr0Z)K8jSawrrZdbo!i5~hBaN~9us2lRy?cj` zfn>18p)=|?vKJQ}FpZGr>%FuFsI(rYE*?~F6`FMF&GRU6&=YtTTpd^!M63t?hE`2I zue{a2K0_`r4U%W0(0H6l4J!o)Jm=v*n~`V2%*;$!U!(iu@gJcxODZujai74~@^a=n zYgpbx_zZm>>FO%0sU^aF#h?+-q`RaTk`pTN#xBR0xehoiSi*o=;sV1p>V8(%WN;?^0|PJc@hL(>RTHQOtLvkvT`-W#;PrE=mAq|- zWSvOlDVSgYE4y~?w3;7pX88?&{;BQBf?h%<{;Y&HQJYVyKb<+cB9iV`(w!;8D&8Ga zqixafF58Qx+f>wL$xTZ$DX=Saa{qph7diIJT`);RrOrI)jhYfSyn0pa@IjUN><(pY za!G|rQX;{Il(Vp`HKgt4R^{N+f5w-TlZTC^t<7uq=V!^;`+dJzzn393sIai`uT!VO z*R;0r$3Z}h>8U+L%;umijnu-4-T&{37AoOZVo(83(V`~$>*Z$LlF zJ$3aEYisM~VrP3Su0@&U@}n1JIS_aIfZPanx0MW1x^_Cm=uCl4z|-5?KQc0MVS-|M z?1r*+jA{bE-&K0GZo2Y1$O$ z{i7z-Q1*~zu__M_4;Pl81RLd$Azt_1&o3IH%_b0S^L+jKzLOK7tl;CvkJ*pPcR}-} zGy>lc!{rC*z(R*8a#ST-#gMG15AE8$+h%zzlyEX|Z}Z!#ZKDm2jOWHb>lCj~`W|5# z&>nZ5SX|`_S+6*TJnivNJ7ciXIRsM08&&B{TYE;fmQVA!8d_#^PoUu}ixQ+ERkNZ}FfU>j6TZ0*+H+xenzR3^ca zq;YRbxRTYD0->q?c_^#W#5VrVgU+2lU)jq2(?dy?**rQ3X2mYOtgHCa=6A}xN^7e80J9qBg zxbZBxYRjk|B$Y?ovf`7g@}vGU;0z3@>Uw%HAVeltiiPXL7U^`;t|G@&?y&&Gx$^tx z@c+r~W3floKXrC$u0pZ~9|Q4%WZ0+~Cw^N=={>B4M-CqB8||=S{^fR{EAcYvacM7ZdDm@cO?7fua85FGc$K0wJ9L z^%M-(vVQxH8{ZlQ{3}&a@4Q1E7bMFV9drQk?s;PRpE7hzU;PemUeW)o_{jfmYW<8e+oP{;%X|CdK4y7M6;}u-ma&;m&zaP+Ndn|AyaZ z8zbhT_JU-M^nIh0Qom<6o?xNwk>9zzygZHj!>xaXw1=0od{Dh)QNurs+aAvU@l--= zWb|Oj9}$vOiq-^8i7}CnaOsBZZtoBMtPCth|B+|8tX~ZSpnsg!az{;;`ndMdUCL@q zs7qNO4^wZR^`BM_(A3MbTUknSwI*!nKVxq_z|*}#=SRH7MMW1 z#y@`ii}TExWB|%(+`AL9p!lP`cpoF9Jq}Y75SqNvod`2gFT&RD*4es`{XyE)rWcfJ ziY+9W(W^x_dbiYZOFTAOw^DwuN+9rO^SZjadj9?QB`qGc%$wi8e@EB!o13%cQp^16 zz{bYL<@bGHG&6+j7d~ZR(0nX>X7{+32XTMMrkd*>YyOp;I6Icve&&MFPO+~o`XBsJ z;UK^Bf?0o#fY4ZXsRX6Vs1ZUc{y{+rDJd5VS0TSsoGfEX`d3giALl;JQ|)0EDST?s z_t%wk2^z81jTfhHII6u&mbr1^@WF#0flUDTMwb3hF3iX%Z-@Ze_hjRzM?veUA&k1a zh|w{pg~>5r4>C`GVr@{1pd2T&C0<;$0QB`!Zc0Z!&QK|z(1CogVqc<}EFz;K&6IyfZ2&cwErn^O<}yR|F2 z?*CtPLC5~m(R;h$K437>M<8*+8#i)SZ-tKWjPWCffk)-%Hw=FxHP!r+PMfsH?YveT zTw}n=$;q7FK^vYN-C!Al<2H^7yS)kP#M%Kah4h^}k8zl5#T=(kw-+y1u>bhq2bveV z46+@!C~}4P@y_CgvExFIukn;Dew=PEwc)`I7+B*rn3dql9644vc*ZFG!hvPA_N5=% zUSv|wC2npxKn-c!j0ugvzm~0Au}@!5uXTL#Nn5%mY&OYo&ClvbHS_BG;Pj8r@FJzO zuNj)EfsC+B9Cb%;6Q&xmHr_%bd1OyM4;)*lsHnIgF5cBLxCz$?9}bW+3X`kg-j56L zeb(b^6K`ExabH_v;gcwTT~yEfxN8YFmKLGfZM-qn+4Bp^W8uCB?7)Y}NE&4f3<+onqIV{<=RRbG8F21x^ zd`M$*T+Rc-0cYR6QTzP{mv&LPPN`+Snz@);T2n!#CwJpWq-IL1wGx8E=8} zw{%^55q;LSK+DpL7{W}zNE+>71P<3u}`oJNOYYO?=%9xfab9Ho)Ydyk>wAdP!xLg2uFULkp0 za?8dOGt{5oSZ4TjMN3z*Rp=12Jl`qSo+RTdN2JEe1fD;6^18mhJ{ZD;BY-2)OO~aP zSY}M(H;D}x^y#A4`Fx~3e}faRS-a7m8aBb|I-UwAFu0$`+R**giyj8c9Xl$6KX6>? z=1n6=d(TWyTj5^2KL?u%o(IH#yLumVwq6I}g^L;GZ0KD`;!LB0x%RBK$0`h)YTo+1 zK!LLpfp8OKb!K6@aiH+@=&GtjMn~kkcd%(_AZ)o6MQUGiGM&L5I&!e9YeP60Qjgkj z!36LtcBg8pr|ZIRTf+%<^>b}`!|?o?*j@K{uuis(bGI$-$EN{;+650#pR@tk>Sbfi zx|PN=8Wi1NfMM%Hl{*g3=zR#wxmK0p?~=VFD{L={Re|l@WSwQhiFrB>BU9%pkG#4>IL{oaLO3QaH$X9zy2HRY)xBr8k(l_$8eM zpODVN=rFKU1tyb3DF`&V&u*ZRsNlBw7U}TX^a9gSTUQ?>SuKN`0bM>SrzeM7AZ_@( z)J$wa$`xgS&m+5Hs|UtI`5&+7sRlwNk9z)?pYZa@lWh*Gk~cEpDH2@nKxUy#_&-oY zVTcwX6af1;plA9CJZh?Gk#3st8F@7>4K17~9cjfml2v;495;Dla^Hvt z_V%wyOZX`@2W<3XC!F@(oT5)_4z)!;z35k2t)lwScd)@BD^(34vU!eXRO>Y9-P?^Zi^0g?RqGl_A_pJ!_?kr6N^r zjk9TE8+9Se|9pKxd~vME3yFa{;WzlZ7H-~A6iw3YzhZ8WD}b*U)X)A#vCS9=Tb3+$ zzf$+r&T~5T>w-MLED0RSF9FeD+gAIb7`2uY2xqtxrGEKb?jpb!NGrWiX~-=w{EQY(!cPHx_?tLR9E=BAz;GO$M_U)ZWca$=Op$?3#myd-bRBa(-@m~ zQ<=3#eX>8Po953EzMOHVJN@cK3=7VX$B|wj>e9_T%WSUYbdPiE;Hb!@o5ei4ZA8-Y zqclSUVjw(Q^LN^eRtj!UaHsM=;Vxl5ZCQen6^sMQ^o!IBy;XZ+&BQ*urd1%_te4%; zQ1sZ>#NcxsGY`92Me?S9^ANXj6dh<7*e+8_4T-}+fCWGX>R-~7N_&n z!#nKUtaM(+tvEjPrs?c0dM-*&$p3VM`L*zQ?v%$)SWJ82M9@M?&D*@v!i`5-i5PEZ zA`gpweBLzl-YxSh(;=p=w93!U{XG9TP99)mSttW-=X$15CXW;q{VbZ?$JYkcH7~j3 z>e$0zhAha2O}J5a)jZLSIW2L})Yiw4KDjK|W=ULU@h zBX*8)Kvu?O+AakbD7i-X293-;t}!@k2;Vnd(7OQ*(Tx?Cql zMgDwXrARRDTfL0G*t-~!!;B+HJ$@0Z=rr57CF!gHdD+EW>@K1AvW)5?k@K9$yzV=z zF|Q>r@g+JphSwww6X-h5iP_#KFC^w_G=#z6Vc6vK4=3hFb?Q`4Z&@OW35Obpt?Rv> zj^_@;CUe8MFp*QM_{4R^72~JDN*?$ZpI+PI9cuOZsKlpR&Ljh)&*>s$r&U8!kGXHg zV##~GowbjiW}Fn9F`rC~^6A1QnNQ`s6Dgv`DC9=e6R!Aq8CRK}%Fpuci?dZ+nc;Vt zp<$P6ByNAJ8HlTqVN4P#)%@pxIExcjFSWL11b+>KMrTGopj9lI?+0Jyo$C9KU-)j* zW=-VLl4*V|xpkjnYO7SWmq$*Q;GZ zPW1X~p5=u4xXn54v*gCx{mNn5X$|%Zyo8nu(lzSykDl=!v>78h(+jDuDz>$+%FfCM z7)@`{Xf}07cqKcLB)?W7Q@%7PX9^_2Ik!C!8bm+*Z{7Y5l8!KwJ~K^r<@wE6urb)}^hEYIUXPbT+Ez`m@*47f4dxc( z&AFA*TyOPuW{S?u1r7+!7YG~R1M4Q`(l_WPposO2!qfPRl%||?^5<)L@?>wXSK&a$;yTs@o0(|krmy!6Ws^i#2dn0K=>5kDtx!!(`H$5( z^%xY=RLgBz{gF5IM&z9f`BC%pUWKj0;$4Lk55l{s<3nlFe9_)ykh=MhSB2DTGWntJ zf^?4&Cb9NP_`{9ms(3GMlMe31=1I3q(bJfn+Uhr^waO%qbY1w|I%!~?m0U*<&rfaL zd7#CvI`VR4L(;KBVXr87{kygp774y~3o)xJexcj2lw0^D%{Na#8E|WvAUKbG3KTXZ z2n@ozKkOIor}uu4ZgaW;CRVAC+t&F0t(>9dl@=HH?8`{T_HK67q4rK$3xa{28<*?D zH-g-l`{bwp;C5mCO2sV9G@fftn#66kCrW&k=~|nBfl{r_c(fHRYjwRK9@EEwH?x0Ab?P2&)guBsF!V5Au>r$_>IoIXiL)I21 zRpGHA`)dAVAg;h80vjlrT^Pwx)jR}Cp5m>-@5>^Shi6PsB)6pBhHyd zzlrBJ_@RjjxaLe-?`ruluALn7rz-w%b7ClA--*QQev|J5wcV|KV=oLDh49iQAs)Yy zj(uxRb+CR`vRI*uk9p0wM&UlbzSi%?N}dom^CEW9Us#QOOXF()WK_a2LX2OFj{4go zsq%w4tCzWHj|kl{^{Z&WR7P7Qdr_o z^KhTNa)SbjglsmKtI->frEGi3Wsg4#PD}L^ubwHtI}%q`c(KX*_FiG|7wH969o>|m z<&|OADz_{oVte0Id0q(DN{-`R9{uC?;;@p`J7l0hEr|peXi~q~UReIl{aIaDIcqyS zqCJU%0yPg%3v>3a?vhzX3_eghim0{m zkISu}9hdBkoonG_# zS9rvtJQZyGb?buahW(ZbIn+o+6R?WIG95DaPy!PmH>@aev}I&j=YGJ%xFYi{Fm|j> zx!ZBsjNWu_DhH-gSS96@a~7wt+}1ABe0}wqB$A{=h~CmXT(Vv`wODV7}?>7;#BWssc&-QGPvE7G{MNdLH03WuD=u((#aSn~zH$32ep;ZzgP zo}Ss=3@>@FVmM22$$WkBE(UM;IEcW=dJ5A{7{i5M7G3}ITNTeWE!P0!d0syn6a7M^ z^w{Qk{4-7E_u=8owe2~S%T7_9vZq1a6?zjd>dL}j{)Y#Iiw)qHQ^VX`)mhGwEzDVJ zYTIedo7R@BiDo3oW8QRm|Fql5sWJtjQkk!f#_VS&PsvY>I0>5 ze~4m9^?kAC-9}~_g@vnm{8Y5E*>;fqhw*fADV}5S1XP$b z8IIvZvdy1M@3Nj(R9Em<^sr}ldU=rS@-ZyhIO*(#`x=Zq`s+dGzw;^+1Z?ZpE-UMZ zEw^uN!)|*JC$!S@PJ?TRMUWUIM-kae7{A;>#@k*r4itA7P|;3w zVP7&R#hVFA3U~ntHr;9R38{Pm&S(s-Zi_=cWMBeX3=62zT2dA)|g^a?TV^xGs5=+r4g^duqeI+Ri zO#VHvQ@i$9#$Q*pzYoR?z~XSBej<@hm`m>Fv*9Zkc~!6_XSk~dT?k;aRK3KHiLT}0 z?`$Ib-EQdIUmIn%&zSZ?YX`gq!rpU%+`2X3Th^Z1Sljy4;t%K9-IpQxj4>qM)>ej< zYf34=XG~bMc(I<R1X*}>kE`OzPxFD2Mi@7=r-F7jx}owLY3WwWT% zXnpQp5!}~<4v|;G%!;lQsk+fa%t_R=%AjBy@A=&4A~?mdbPHu8UnWdrd*BeuCg*$c z7Be%u>%oxQ8g*==5PF_V?JNfM%O16KyQIZPnBZpX%1{%&-Gt`cZhaDqT{f+nqYk~I zP&~ABXj&Q_60S`<3U!H;DEybJZ0))KSl7152pG+T?@fc^V}|^DW?Re+0aAo4n1zY2 z8-4_nJqK{ACBhPX41u%)tOmFpAr5X{O{OaELvohcojEbllVkdMt~uu8;P2d%8Txtw zQ0@GQhU?hve~=xpn9)x1!D||kGVwB-*@)Tm{LEA%jR^fS9+$z7^$cyiJ6+Y}C2`>L zb(o6FL|La#k&+Lz$wT~0?;fOTe!9&Ha2HnFT@z!`Q(Buw1+FTAhztYN&2daD{OjWu z|99_AJHa#R-%+@UL8uOS%-7x+?v+o)HV?HIEjpfhxB&KSN@GGXKIkNII`@R3=#Ckm z^#_AEGxBt;Eao1}30oU%LnFharKK4o*&#T5)8ykLA~xM`yc+st|bbBw^n004(!;uEEbr00o`r;Z}ed-l!sG z$bV}l*_-4*FF?p;bZSCTdTk*;(>Fr!Mpw@c_MFLPIqddVtvJ^!0TEWmOe>PIK4i9l z1yTaD_jk~r^Q`2IO4@e7daxiMP?LU?vxN}a)=@{{uC_axAfr$nRbQF>^yIRRVjRfE z`^@QJG;XHXrq)0c*%EGY8R`r;jYDKQi)xnNB9ET2- zXMSrEz@pm+b6I*FB**A8r9?;bEw-ld&Y0_I*1U~}_ji>$?CTBOb7`VQZMch6RyC|y zCk(~uYa)u+?Y>GC!%s&K^Sv0U2H03XaCOnOrc?ulC$S|zZOb!L%1QHNn!b))VM%hk zWmUV5YuY)t6A!3V-;%7rjH8ZNp~8uRM`vy_DgJ$hl$AVTXw@=FR}mI)R;HoT!G#k-m+Sf=K2?9iD@BTT(TZ^SM2OpoH@(;{gJ*KJ>7cye7M5P}jIa<4HpcZTH$=p;J zE5pfIqY#SC4sXv4){e{V(~{W5d)%jCOO8!>2hr5@t%mmHev5m31o?}KZt0pI zBLeTf1sHX|?A5JV|MjNJV5i#>MjEx(uV3y@OP}sUND{sZKM`86Xo?$lSt#jp>2cZ% zwx^J4>vbX_YKKe@8z~DQ+PDHpJo-}it}T_&r{b@#zdRc0c6k9Ej4>>IT<_8v|xHTYoz4?B?VwdE#@oc$P@wmN$OR+0C5;|jSiQrM!mpI`R;PHZizK1H+xBPpO& z*IsTu=xnuJw?l&e%fy4gwK7&)ORKz2!_KnWBbKaeltU+iEMJs^xS7AGhqp{nZpE^i zixnYUbD5BrN=6VeiaOEg?-pd}#dgU!gjgMB+B`bK8r7k_rUWgK?cq&;Ap6~DG1E>% zo_T1@V9xyktV_v7QvORyHi{j%w0wK}y+4V9yYzB?_yT4ZwLvxSDlI~K_pHD3MeJbt zErg^bw@>$CyO}z2u{FvgSEdc-i_D%)6H+}O(K&c5O5@m*hehJ{l{jjK;6%i}A)H-x zjUMmBb^KMARZg`y3_Jgl+qV^TX;}u9ssP-(c4=0KyJ|Y zXNDg|CwByZB}b}fK78c7DAwqzE|sM#H+%vedu3fKzNz4hH-kj>ZP{qq)!$R`GswrK zg_fe`HsqjC7U$f&bYbk8NoC2EmvTO)d<}Z`q#kGA!o<`Ok#)XhYu>!D3T3|C$sy5Z zJzrfSIm9G=!lea!#)=Xzl1bNKlWC6y{|_7f=+)T~sxoofMwCL4J-xKeXiO_tT#(CUKWT7g)a68sM z&~>%XjVX)*9iv`u zobgkN!KVK2(vgisz0oFv`B}c)V-sADal*e2eSG~tp&q_Kx6GRmhfbE1cU#)#cow2f zJ`;7yS}GZYIn#8xz(0~w zsC*H#Ysak0P|5X~1)KETqZkp_KebPEnKwgBugMC+Yw!KlqaZ|&;+lkgdr)ZYnTS(W z&A<;^i2VwmzmUeipsf5RD}&8xxk}<|Rg1)Vc&l&!#`vRxMd5Max<}g(N z07aqfI5Aek7iHxy2bcSDZesA-pW?-xtUWjq$y4`EO?5%|22c`&Yam(;LDCrPB^Tlo zsSeec3lKx6v;rEy(ks^No;pL=M?APxCZ5;R%Y_sY?k!P7e_x{hKBjNQ+Cv?dH>0`m zVlQ&=IY;$X-(tB6sjq(+1NI;+S3m}YWn)#}7~$;wxgVwzjK%zySLHpmBjVt6E*E|+ zzIB1dUNP1#=>T|QKxQrLl{+v2^{p&++ix!#Ra1(+GvLmLORwJDq|-I(q87v<)4Dp6 z<^29#&?$(Wdxwz}!I6?)Sw;c;`aX|bqftdkuYIPbt>fd9X{;w$6LPgqhu5BK8g&~} zmU`qPzEVX)F!g>k)J6k-3G^EK(^A_${Hj7i%X(`v_=wH1+Ro8_Ps%jDqu3V!p}mXB zhPq>~^6&`cK;&ME0`_s~-(orUqk4dHrJ`6n+it_vq9CquA0o}*%foe+~NT^ia^Y)#(=Un_vnp?DP^r#!@y!QaSB<}6Zmw{S3vI#?=x zn$fcAHl=*)pcHvgUoqN?dm5lHL1*Hc`TE?aWVfp*T38^ka`>10yT^T`N9`{p=TcQV zH|Bt=*j%sS{-bJyu4cL$^ifp%_(v>bqQMb5}rc~)FAia}>4mS8yiiRdgDAIec zA)ufjAiV@a7pWl$J#@}osQdfQIpdsr#u>kR|GF7NMY58ttTo^H&h|V{N*rstlhW%d zU^w21hVtsq0+t4t%H{^%u2Wb*Lwe*odkr*t!yf-Ll%~7i3gfI9$ngbg&i~SlY1VO} zS{uPjI8$$^Zm~667?`a?)u}zu$;{V~HPz>m9pzrAZMh)acE~q7A@0SeHo4ar@G;Zw z+319&LB$3sr$P_p?>wbe8MvBHpcJZ$D4zXzn4cBGI;Kkx#F_bUt_e`4G(sZTcT(Z* zRF^cG_3h4MwC83#gyugNnvxY0gWRDiV)xI_k9~d-3g&vnqRu^37!uUKlr({ew^HfS8t5S|nS`6Vlr_`)e=On3x6(Dfc|4yEU5sp~b ze+E!tflo%cd=^xNGOkXYULMjA!Sd}u*^fu=vQuDl!q_PwRSU$@>Y=W=9?XUONGjpH zi4~a(&(XnxaeW781b2CrPOIn~?oZaxzmtWOqeNlPgK|E&oYzNEw$?C%Jg$mi&@W4Y z4k_HM0tbbcMcES8QBo3Bx4^ZVFUl_Q2y->>uY#5mlFo7|jF`zQVs}cqAnCK`!gnV2 z0nd8dX((NvLgo8HM#aAm2~4*ia)%z^zDfOXJtx-)8~vh`o)X=d3*a(-w$PBi>a#8_ zsE($Z^?k0fg7uIjBl;J|<{%v@Rn_ltpRQ5$;_P}W-wy_KYK*Dl!aQd3XMNSE{E_zt zIJc7{&|gJ11?23J9p^?S_%>)dc00!Wr~*JWwl!`q*(oOzO0FW_zq;;_0J*Fcbv|2L zy~tZACwqSEqWF9PvM187okf$;ify0Pj5&3ZuFBHinj9#M_tnpUD=JyukT-ya-11=H zj01_A3RR>@L4%|lQmQ<>qDI&bSicYMdNHwgf`>u;E6T(!P$hu{d27jq-&#JusW>?K zjeJKH{5-gpjHvizIHKtG!TL^EYmx>>C+;ZH8mc-vRJe$_( zVkb+N#35I}$RqSW=A!?nkma9Gg1ab}|LKPw4*cBm6~%G<{iL8#Qqh_7+X0aMwSNX> z<%Ee{?VR4Kg4*GbV%mSaocJryfmi--r>p;KhHnvz`>&h$O%(eD5sL-&<<(m}Uj?z* zl|f1U7^i>{1Qa)AYQ?1xY#R{^U_b-it;)^KFiwl5n;>G_Mq4 zD$mrQ=LVjlYcsADa#BcTMC!fU-#|j)xWM4rgmXXqxp@RL_(%=+dD0I4&U7sMcETiu<^p&tvB7y$C)2f(0ZtjyYkA_9@d z7#e7qhGSgDVT@mtyK&;1Ohl-SxPS#FFV{xwT>#M`eqV0@{m{%C04@OrQA0~tppwDp z+ytPF-t<^&HPv19oUPldpmxpcjmjg_Q?z^p`7J;_Je^Z{8HPnoH{Wup3aTcHMoBf1 zb{GLKM_!wwt4mpf;0L0uH6Z2z8mr+l&g8s3W25}r&+(lPdmi>~SmTxuK=;`POL5a( zjDx%YKEyiHpH@OiXs%*)jCT>(7LZSa&y`{{Qa&I2e&2!?&;Y<~i$mxFIJxI*N3bTR zgH58&jhjTzZUU;2OCg`;aUGlZu9vN#HsDMKa$J9I%7kr=Ro&5q=8E|P$Yo~a5dLeA z>vM#nK`djlrX-ncSE;MrFOhZkDGe@ffm6d7Jo)c7fMKA>8QcH}!17(AFDc^}0B>Ex zdXVZhLtJ&4y$vVwpf7%LrF@+z?k~uF4=2SAF&P5`@h3|!gU_K)l8GgSuSgMjZ9>MB zDfk$YKt~bo`c+Zx%zCHaP7gG97oja_y>B=brdZnhCoGG6hl->rn6oG(5!!B zdEY9x?ZW*+W=1Thv=`08bCqfaSd}|}5d#r=5@0Y%0(t^99SfcKtHdYe*YV`Pzy^TS zL?KMHQ5?SA?`t2cMv;{Puewz86)pjOav)R2u)M8=UefwBV7v(7qR5fX{ZTe*xwLI= z1&24}4H60OWH6|c;BF2UslU|2r{G-4iF8h#CnM>$r_C^5#nuP%ZDM?bPJUZBT|{;< z+jP+fbV|Ttd8T@T85p0Z6c)g4{($y1)1U9lnuTkN@TQRS92^cFJYZiE2AFfNweEiT z`yK#Em-ll9PK{O@8_G+Wnd-BRTO)_C3FrI**>F_GT$^?kY;-Oa1U(N=H5mC@D-$% zq$GSqAv>zM1mc)=Q)8OnYPwuCFx_(nCKLlcv7ux7wqU;e+O9p$lbJ;W704uFY|j-q zr*kF*)L4j{>WU3MkY2&AFx8*!*P7aw=zbwIs_0o^*I^IvI|^+rZ+79Lvn$$zfapM` zf>MBbI!Zqdw*(=cu)sLR?;hBuJ2?7KZO9>RS3ka9on?ZbB;BYMEOIw&>XWp3iMWEAVPoKGvCi;31AcOI;VZ{? z)(@;5$fD6k(y>^U)QbWg)Z(qAm*1{yhd+@=*Ro?u%65z7!T;F@3l(ZHHf=3yn<};9 z3on2fO3 z^V*bItY~IB5?8YX2;2JhhWyr;M6kow%Z9IwzRyHumV1_eAD*-=mwB@ijQB`gbgzlf z{rfC5M1(8dxKG2c-5QZn}gC@okx(CWC7W%<2Z&m&RS5r}kye z%DU{nBl|c}XYNusiPF2VG$=BZC40;bfYrsYp&-})DVv8(uk9Gn4ux={X#JhtW)z0v zGxN*~Rw03=y)CXSrn&OOvgGjO%Pb`*X{TO>va>ZxW%@A{YZ0&n8mz@m8J)<DuwTuYsF`f-4#}UW^p!?@Zjm!1h6K$U3>e z29qlcv%*nSL0*30A{%@%&Y`HOz-GTKe1kO04Jzs7nU>zSOYUS}8VgH*W7eyU$$hL7 zk$M*_iCqNw3u_3bedh8F%d2#~Eth7CWLIG035dB$61e9*L3BcqzjBk-N3}*If#l;< z^9XiRng!Sx;7gO^jG8rTzt|f`Wo8)5T5NI{z2@}HF)y{nUAYPDIsqfZ!GWAq82^FT zjOoW9s(`F%JMQ|9k^l%gdMU;WGC@rJ)=G8R*>Z`kFNzmq|~vAVr_ zzYoR(Upri4Bc5j?VcSr4qS)ksgVj-Sw;ZT;A71Z6eZpl98n9O4oR(hc0Jl{4y-Ifo zEMQ?2&p90`0FUZ#f5moTNcVX^7C3Em;A%^(=Ng`SZ*@x+z`vr@Cr8P2q0c2ihZJ#tCG5;Qmx=D0Lel z%*uN<(v)FTSl3N$Bd7-u@eZpdBT)k~hUnTVDZj~qTg`hv0$odvl&y4^jL4Va@-E{d z_7QMK5K!rlMt$8dUA0#<=YVy5#&e7r2)a6ol%-G(e)mz7p2V8T_W1Ysp3ZT98yf@! z3#${^$`Kb3p0XcBW1q}9Q3fGL);n}zR+&Ro;AzP;paJV;rx#9gazHrd8^D$Tx0V|M z6`8)sxPEdKxpagf1052`VH|p+aNfqu!{HC`!eA!mO6pXOiSd?6q?R0OVGNw@@b7{2OQisx zWRN?T&zNp=V|uD18Got?R*vrcz*{Tl$9mONB&0bs;Dt3qY(+%)pBPdO{JGm=wHXk2 z7?SDBdzL3)S5?G5xxQ21^H8H9gcZpB-Of1}Vvqc)sOsN`Z-`=}0gJ)wOOipzO&HSO zhM2%l+Yj@90E%+)|2lByk@baW(%27}QNhk%pT2$M{{@`s=V$ysWId??>4#EY<>d(> z=r&;J0NjKqP~ZhuRact|Mf@19|M5;Oe~P~PfRBxp+gc@7hJ=KCpHlOYdWrSbr5 zF;+GaIW#&t3M26C07~Ul0L&Gf<|abr+<`dXUl0E4!ML_QYcT}gjR+J+$h!Lyp16(PL#Fpsb^f}Zd*k^669j2d9{+mqN?#QR> z#!KGXyGZSTT(;-;dIcl9$ix0);UcztXY=pb>Xi$e3wt9=s*c&--e_xgVIN2&^z|*f zA7Zf2{3mIJyz{tdh0>bLoRFd3(}Gyr&^elQ7R_RZNM7EPS0U~t0k<6~)s$=DH%rSz z7#RM2#=d^E<|)xs4eoSl%F=j3;awFr4uhS_J)*^o>i3f6w%6IO6cS2jgDt{Sl4W0Q z-JBSd!?mR_$`M{CABZ!=)(u%P&bX8TkB*AQLg>HoSa!T%vHn8ExbPlJFXxL1ZK@qfM(L&5$3 zv>Unjf9ijCF6^lVJkbH4L*K@Q)gFxXROY{t21`8(@V9@!+HwKwRgE=h)4H4W4MXua zW3POXeYAxUjg@8}fXean!P`F506H z+8{~(6SsrB?hfyn3fXjGf?8t6QbBJ_aF_fQ3y+TdBBsPXF{KB%odyN~Z3+l1RYVSk zM@OXH#7Pvp!6QH|`Xn`^p`6u`g3%jrCb99FLJ$BM%IUL^a3vsZwvv?Q72iJc9%&~?_HvH^^6>-k)y8^fo z%%S&z@*7fnEx(HXfDS63_{XG?Gy8wd;s4)Z%;k=$>7d`F!zGFB`GxL5_S8D5heAcW zo{#{v2InmD%OAx)=asOvTvlMvKP(&b=Adx%CN5z5vpj(c&`p8bqGoa z5Qhy&4UGYn#ei^3hK=mU@eKA}`mWV-{CXulE;fv9Ps%jwD*-$?x?}mK&c~be(tYw= zrAxz0u?_FHk+I5Weim4u61%br8$hq`q&Lkj|CjlQ{14`%e8ws6=LhlM19xO_IW?w# zVT>VCARA4M6xtA~f(X;{MYaPpPaZXEM5Py9xy7kqdiL&WPy7_~+|?jzuK%G|UClOq zlmWXXraL$9B(&2FG_*K_f>W^xFJlFS+@-dLhTqpaM!a>Z{B3#;$~a=w02!&TQ6W zj=C6WXeA6O3qq|cA#dnns4pEQdET7t-BENYz1}MP8C`qR=N+fGdM33YbG_iMo#xjw zGCckjBsFz@B<}XKXMn+{Noxni%m;e*L3|`FaCWXBgEL!q2A7FcX_?u8v0I zl8Ua#*7FKqGmJRk$Sa%KH%#v+4J_ZG&c0Nr*q>1JT<2i-MqIrRx{F+n+_}i?03$D6 zg~&~*>-|o%)?ky;y0B?e3W-37>oKqV+}Bs~v>=)L6`aQccG@L#92yWa7Jps2pNA(Zp^GkrewcadA2A*ieB*zc30 zi9SAKQjB^q@c~mNTndz(H@-izWNSYn-dW}od0gJe##wspeCFK;Uqu&Xdrs!>tne-- z<>+BOn7nM9(b^co%hjf=7lu}D)i#}onT4ucvORNDH=w&YxXUwDPXsnOy}yA zS`fpmeX%k3g(MiHo?2fvMyqj`4x(O;4%gJN4>`D|Z*yP@cQqKjPdrVzRiQLACagA9 zW0djjl!$+2O2*$Z`zp2Y)q}Xq#c(RdDxe6iXM-K>HeUC3)tVHgOPpoA-fTpRY=>Q#RsIOL_t##IpcNqhEe_nzIm&4I{7=*ahuFQm@{ z$N7ya^s$NR$mIvwol@J<(J;$FC)@C%9_y}D_2dPRN408<6eX3r=C7}>i#UxbX%8Bv z&$Kzs7dUL_?%7*N?B&RKO%&v~6c!R0tC*k@;3W6wIUu0K^)kj%4sCB_#is8ELbxDQ6%(mU6>Dj!7DeP|Gu z3*TI&*K7(u%CGR6x2qw)X*WxUIicBAJl#-J;XyR?8wjc*ZU%Dduf-Rbo@aQgP?)@v zzuBHMS<1TQ<5-jN!N#s(M8mT1K{01(%TMN zF_StyFOh5H^qj+A}=3)0$$9s2A|58#|6 zow8L^8tgtlFVzpXd@?XKOs8sK#Xhu3@|jVKS@E|KdZD}D=&N$iz39qV;$G-%^@`DQ zde3)AzcSkeL2z5zPMT9S71SCufj$jwJU2hDsjJK5?d|Pn+;v9-+s>WM)v!Rau&|JH zolCfW{dxy*JMrM3DJm)guVNzTIQ@+U^3cqoq5FOe6$J$y6S_+a3nBxoCr%^*536K{ z^S4h2kn~M4TmYD9GUi-6##Uh=OQNUW&aQ$qgbHm7{;vP>r3IMItjg`k%fKQxa%B!jdq>-o!QkH;<>cv?J&hABNP=jVRMnAXRhlJo>7o8J5WWZ@-AWPGiz ztq@m2J*J>We_)&@U8!oHaycnrt;d_y3*b@!Q8{o{B2pwD6MN7-Fqrljb+CIgFz?o8 zmaY1`-e>)fm}4xfZE=@RvDbxqv5K9}&HTuwAO3v7USc|YSr$iiOT8`0{H90hZ!DKc zQAKjjxC9HPQeU>%p_m*cgV9|cVmxHR!>gv?;>}_pbnOvMZj`yC&P8j-V5QZw?oGUm zGwGxqW0kZ@Vw#Og*^$j+#oj*^nEJnU*-L>n%JWA@tN~EMvt0QWAyq>AEICHKWr<7D zp)*)1j!FN1@_Zg@>e*=JDPJR*u4P;k57{Lt+I7`o1l5-quIRafV`A`G<$*m&drJz4 zqK!7}p2FtCF4Jrsu+eT8QH(icr8Eh+}fba z7caur#;qW)OsiPS@&b~2UO~ZT7dzlQqLz#>F`l{FJ-nJ-KKHW!o*A)NhB@7dHfSwI zM%c1RJ3!{>Z|Q}W8|cRlU{)YOa5FJES<1f>7*;K(zseB9jdYVPl+D%ivaqqG0W~8$ z%ge>}c{qZo1a2L0<*PwmJuiTIOHmQxOUi*YZ@jqO_EUX$wxk3MzA2u&yo91|L?^BXtJ? zsW;k>o+z2#bd+_yGa5%g-PL&m|HCG%UlZFhqC8T25R;A?8@~3?KYO| zu79@j(^lODQ^Jwg#Ve-krR-BI*WO58SyB~pUp+aVi|&ZAAlry{O|z#Q({Ac)wjr>U zqosVxdhuS*Ia4$7er5FXPt>=id1~IS(?KeOM3Q&%E{52Ot}K0;^WgVXZG4$X_(%`L zR;wkYWj=@E0JeQYrbhFZ zv3cKFt#`HAd((J#12`tCZ@Y*t5FO#@0`gJoXO-J_Awgcuw0f(J*#OSy2~bGi z@~49w=sWoq0R?91h1Yl6A+%ZqlbnFpg_%U`-2mIk!xxE8M~hfsqg}^N65wbzcvqIg zhhu>jebC~tVJMtjrXfKW>%1}=X7L*hEK#9tABV>sT8uGNuyZLCiUDmtN^o*=(hZcq zI*aX$JV8VwOCb3gu=oZ9M)lfO_P+I+t35Y4MdH6r^C-C;U#pTbw}ELcAMDxfuvnEZL1LmlekJ1PB7Fa{VZWWtTzmgq>=WXjepmCQz}&FX`WJc7MVD)jD|EfHWnspKek=^r%WmF}5EJ<`&#$j zZ}k;iR{a_;cdKu9MN0X6ZB`#H~*7rAcp{}Tvr9YYD6%0RC3pDyGpPAtt*!#?iUJE;$8q zkwmCqqQDS&MMN|}nB-DTuL{c<@O`geAI{Xtm!F-T?Nq6@wdyZJ)p*{c@t;30j|INq z`%3PLpq zuol7JAam%kb(q_EN*5{|2WbBGk^rN{ie+frNzPhKYe!4Y0>G0+w6Bdl2H>8Y7BG8l z0VC-sz*iY(+FC8c@c2a-Pi9|x;CFe$m741uUlb?abO+#jHJ8a&R<}wyjol$!OaW`) zkaZ{q)Ly^{GR)s)nr*erPd{0>gH;z|e+b4KAe-}gkxr2cPQTmj6s1D{-NxB%pPidd zvb^;D1M1BWmI`&gjrjMRwH9R=@5v0dNuR(TNNXTokHXcK`J(Oy@kVuBP+-{+xMlQ+ z@*!&mGq7Q9aIDQ|Al$zhaFbbcFaI zLfS*4k4xqAo9bz5=ARea?%9?157RoRGnkt0wtqcd)XQg=dwP0pc$zKZ+Blyp7IL9% zLb)7vq1$MTJZ4oZRbH98t}_0WEGV1J(h%N5>4iN@EXyc;jl<nayB+Mi)YCKjhr7@6-0?hUbT4fD_bJ z(3CTp#@#lixcWB9=cWc+)ZTd6fvr;`izU4L-nBrXRI@MM0Dp7xGjTH$uIpde(Hl)S zQn|5wRsqn?@%eDyz_oVQHfV?2qWX4x!wTTQk6grXh{+dMuBZAAI>s3MOJBQ7v?%kV zv%#C&JT~5noiGYYJL>Es4u;VmK z#3ls$1qYCs08rAuIhPDz5e>kc6bZN!2I%`le4lKFRR$q-3E4OLBQC}-?Zkr}{rb7` z{emDGIM}@y$JHX^*VEqIEf#u0;{@zL0Kc^ z(pV%j28F$bu3g&PW6H|2d!Bzyg1)> z2--RpkeSpsH)ABm_{#bC_(X~z6Qb;N?p1kY1~P2JIoVF*P3ZP#y=bP6*Ov9zPvqoybwO8B9saG+|lK**6Ry$DQauDX28rtx$!?;@Y0 zwlx5gM`LKH=-$z;z^JsTiBphD6nJm-q<)}9EK2R!XOw{+kdddiM&kx~lk75lnKS8yZd2075B=&FS3# zo}8w*HH>~hud5D|yO^Rb?z*xE`DgUBvO0KKJRRQWn|)TSO25C#Oc{xuIC`TG;8mUT zc?Z(?1Ur4KY>5~e;XRnzL#xkT#QXPOTyljYfl_T!7c=D1RT6hwy z=Xm*~scY12&7q>=0MTTdT8(AjRGSB3j7^=cOpz|geJZY5!@v*ec!urj`6TFbR zsnFT1{25^(B$C&Lh&)sw|J24EtTRiq`R+Ej`f{t{ivcHPb4m2FRg9$B5~at&dXWCX z`dm)s1~r02aKbw}<)N1Eq?MtA+B})RcG+MC;@hxCM_xsN?TMAuZ9y=HO?cKHX1ffb z23!9yUHVdQ+^f?JK2z4fO+_*;R*LyHb=1IjJ5}%aw#$xO06g2CtIp6(oLm`?DSlUv z&)vOmpVYJ!v1u-@sIZ}rMB%HO;LN)1mT}C3;XViJ#dq z%}6A0iX+Q*Ag4)UX*r%*(tqpGh?_FLVJ`7S!PC0ivIRyfrO6tzh4Vc}m}oic?0`NC zdDmF!zEe`dNVZt)y8EXn0=>FUK4k!vV~T!0Gms0s2ai~b069(^U>cv2wp1fnrd;H` zT-Fi9MQPg?)Hii$?EA0@iprr)TieZ+Rsi){Av99D^a$?im?X%$FJH8q$?o)OxUTp% zGH;-5hi!c9ph@9i-W{Y+gl)PJwfBp!@T1aD@eHf7%lDG`=n`)-+Ej9xYBSZNV=Syz zq!a#3dDZWwm-J14WxDv8%AO6oOEtPdSClT>QbLLkBna~GVwI@qYn#nyWa>|P1w9cb zShF@6Y3K+X)syKcQsEy+Z0KRW1?A{Q%jR)DIlGI!0t*N+Icagq zvdjyVrV7Bylp{sz-X82f+1oPE-mYHU=lIIDZ1Q|!LV`JMfPm=xg+xbZfr5Db1Acom zs2>FQNDB&PlX5mdZK9=JRhCk)RI|B4{5&_>Q23yFFCw&b<;s;snP$)sFr?ADx}<33 z@qU~3gRWQTz#iS?zA?^r$voxEYWoN_fup_MpIL^^HC?op)80I$$V``=`IpB=l=p%6 z5Z!ET5@lg-U4-U1DZvsN(w!MVIi;_>+{sWhE*%m5@Y&SaH(@%=8MrY&jJ1}|8`CsX z@@oJ1)KRJOkBhreQ%T)MSN0CbTw}G;lC5-$Is$l6DJl$y2&lJg?cFXjPF?OtL9p1$ zMRmWApaIwi)kAuP5dGiG+@m#~#Wq^`SZ&N1-mM<8_{b zPfc{2ZD#)4+v@}Hiu#f{meX?!US!h4*Kc8uL;1pv->q?Y8N$8HWm?5$$ry54u6MH2 zdBNhb!S+n6=NG8G#!5J^{t&$mDM@*b3VP8Idr-EiuZ~As`96w~Onf`^V9`y$y!6jM zr7V{x;>xyKBP=?=-V=1oyokUFy@YD!}?vXz^gn@!X*q+h0&YHpU7m*;=KcWQZd1k0!XO3`uu+Z!;s zu&Ts1vI@EqD4C!-6C{RvA0Ll`+TmoJ-x)Qi|A1bky73Uf7MG}aPDn@%c5dh#0sl7? zrS3whGeAAx$Xs@P=4r+9w?n{PU*DNn(l?QN45@67j*p71n_$<|by(Zb{)NUDGj5dJ zt)}973y0GM{U^nY_c30UDL9Ru9MwdhBrNn@RZ!EzFdMXar|iVvBLB6dFyi8x%jJ=a z)(b!WJq_qmY^3?N1inaZ8b76$uH{@th(nlY-PRdLY$-!Uo7t$!?;aaeUvu(sB5a;0 zV1)p}k>jEs`ti{m=6qlwaM#a4eWsJVk%)VUk`%mwc(7QCVu)uCpXTnHY_;=yRYa3I zn4sBIuy#WeHqAD14V#0i-6(nOWnXT)3HC)p4E}Pr@4~g-@RTZXr9}3J-`$6-FPJ=7 z=tLWIuk1?ZacOU`#4Jk{O0DCNqUQMQUn2uA-Bj&=Cx=G-fmq(s>ExJx0u;B6pb)M( zeCkmIT0hL<>!F_&&;e*g3~y*0IeZq{hOQhhiqjL@1ivm{*=y(4W1BJV&`|LCxpb|l zOFf36kl0n-zU-NhSN^p-hTcHKlwRpkk&0$cPMosWO>6(q%Tn2XWj@_1OT4UO9ttP| zwD^;^{4XQj17O*V_WE`gP~)2w`}mA9Hf9LL0S<{=To6);B&iiQIh)+Xh+AUccqyH< z^G+*F?;_KK`Wr&Z<#>zc@%@Et?QAy;wp)MN=?BY!ZBJ5nyVm3~ya$QcARWkiC-1&6 z(TW)3(PPKh2k?%g^_I<^Kn(5oVa<=j>oq58szU+G<;=W){~gHFvBAOYPrj|Mdw^_B zvLRWQC~t3{A$Sm4Xd%K{BgoZFY?6Y0b7VL4W#YNRbf&I(F7mY#R`iQ3JR#8Mv)fh&02k zn)aH_h*yU<*uUlWwYJcG<)l)1=3K(zpDp#muJFGrwN`@6E z0xioVa0MWN>auAzFR(KplsD&+Wz}d_I|EWn8ZH$|Ef==#(bs<7TB-J~Duyp^DUd!b z>5uHY)EW2huFgTEL|ZlJ@r(p%LM=V?`I44}%i#Ik3TJ8#zJod>zjEfDnRfb0xJ94M zF3-B7N@mat+#xj(oSN}vf2}HppuvUn>wf+f;z*enT}_S(zEVb0 z6=w5tWN2(EYZmL2c(gJ8ZlR+g2w&E5DDX!-F|`wLc;KGZ)YJ;x7A^fO3XC7}ar`SG zIoYZagJ*|ryfwn~}$iA`>ia<_fDnOi%L!asQ)5%iQ6^g6t zUfytTbLaJLbYuDE+&mLb4v(=Vva4r@nymPAkQf&lYZkG59AaI5prG@pf9v(^Fd3=d z$ZnZdDA|xE0`X>(xZ)F*Bddkz#of?$P00mO6pz0xH~w&@HSuGM%%L8}P5xjAJOifB z`gQ>WkfGOO;A-duCI~C2lkpR`OpQEo_%j%2XPq|e^_^mOqi53#fet{ptTdBu4<&_; z+~)fuG6+{4ns(r~pb+4}I6>u4p`%(QRH$2q`(*UKO$jx^N(HaLH*Pq$&ajxN0w|Lz2mZa6+NrjHZS5Y4S(i#a2 zYUGe{R_@giU4I*k&E?|oPOCO&7|QED5b*M{*I>$WVuKWL* zOJ!V1PA+!uZ)|DMpph!q&dXr6HK^>B6oBR+Mv0&W-5%7|uAqqx%%IS97Y+`NfYZV% zuyle=Dw9gGV`2^-;;R%y@LMm_w`kVp5r_y8v$R7cR73OX~-lT{zMImL#q zOnILIZMS)Eqw(?M6X{zvEz4Fl9p5tecQx;YX_QROy#rXTdyQYdAj%@!?S|E<^f@{` z9E?;x@N{b9J8^Pqa&(@1P@!-+57HVLfMEz^YpSX6@nPr(eLXbp3!*U$CYTLJpBl;h zn9B)$lC5$yCvj|5yx%$aGQ{NVCB+a{{hgN~i&T6e62HAg_ufi|l?A=jTIyA-h*{I= zbC)=-y5yW!j!Xc-LaUnJ8pK=AojVsA9c_CxJ+eyA>XHmp%kYICag&`5d4UeF+rg5z zjN<7JMN~PZs3kWreGYzx?i5jElmKQ3Twl@FsjTj3M%u15@0OO~uo&-{w_cqU&2Hrh z37;mSN<9|3EeD0&rl0XNOFvrwi|Yaxo4Va2a9;QP?3M9WzUK`v@mkr-_qOzAb0H~3 ztxV*yi4R+zi;59(eJLa?TbYtb#3{S=3TA#jjv+DIai*efkn^5Tvu;G`kcTP2q zN#p`#n_s4<{%lgu>?$m?`rOEwk7;Z_MjY=$rS1CQdTfAfEunYswKnA*nP$T3_x$8q zWEIUB*^Nu3Z6v?Ocut}q8z&JkQ`xk(nIrMjlC2zT4IY_>v$+GVR&i7)ciG~^43flb zIt0xp!uMEwV#*SXf&fM7bh^BDSm>Fqb2XFWYZsEu}<0#sEPEmpLMV z9jg8`JS=PqnTO`AYi?E*Hfs_Igw83sL9kNe;luX=gatKZ-sm7BqiBHNGxZgCA$zo02&{oiE~)miN^!S1ev}a+lCS=d+d5 zb9q8!bjw+3K*p0k5{TRw&geGz4a#1<Ab5P0YwfOqAbV_JOXd5(shxaTF-_TpD`uXOb)iJW5GtG`>w^-S}V_b3OGbMoX zjQs`MaaJ-+tm-qsHE~#8^O~+zGRAAioXK1o+=rB~<%SqV)FDQH0b)xcs+$`(xwv$b z_;|8YUTgEqoMxo`9(P6cYx`%A%p$$wzX{xVdu}>AA;?e$)X{#sl!J3l$dsU0@~)=Rc+q;fIzfm<>Qq1s)RO53T!LPi_y^^6&XMCo6YM z)Ml(>UI?hzq4{+1=ghCq`82)etf@Bs_caa%Wj9mcKUo5-$RPsTkWu)-=e+gz&~VZE z-;v*%zxXu=9GUZuT9S3Q2KlX=;xApRmS-q(kLHm#?CDp}9O-$pO-9F1@JqOsLAh_H z^#K-*~@{nI*}7Q3Wx?`K{@GR~L=Z z{;gSNr7zc)p1pp1_>Z&q_bcAJA-8Au5tie}Z)#**=YMju;H4%<0_k9-WhN=@rasTN z+o^~C&^U7Q#PghEVTUhq%Kfo>XHT8{UN3Kdr?(2{PyG>mfJQ{QE`HUa&P!ide(Trl zLF?@SfErv+^x!eJ@Y3Z z){PM;EQ0{%*Y_9rUUuXu?g!39gzcZ-CeVGNn|{b5u`&L9@5r3Ks6W}eF-qLM%&7|+ z&+{8T-n1X{cLt3i!hEq^l)>#xHh0f}n=bhKg|u#68>wesh?R-?+p;72+o(_YWaX9! zVY32H&$6QRkg;hs`!}L?wrcZZ=gq>0Th4i}=jSWhU(wm8%0nJf$Xv4xs_NZCu90#} zcby+=5Lgv%(!(guXk@ARC~i}_A;$M;ZPnS7 z{i=nB?U-TQ37eoV$D_ul+Zehf^o9kTqAPivo;WXsKv#P!I{sk5{yX7@lqds)uwdxu zPg5{|D70jHs<(01{Adp+4)h>;6jS-SLwoPfW_>;>4-u12*savd2W_a3>LBxkUwxwGpTGM{VIpltaGygJz z*dv!#aC(8U83k26FjWor``?5<$d|+ZvUB7)27&($9`OG^`G0bS9xKK|RNce1eF3-s zQU(jRKVVHNsOt`V@xlRp<)5eIf?LdY(Lhv}trwyr$da1`4oC=sGG={Klb8$)j7Z`+ z|2a5T!MxxxrgK}lY5O>sY(mF?HX{x};rx8GaEg#V^j25jaBy&_8AtS)K=m#yCB+_X zAxC)I_z3b~6_C&rU*bA{zTQOW3Lcg%LugFOeJwT-4tn(&YR6d8*xD z1-dMxjf|keV^qh~|Je^L2ZI9*T$;oN8f4^5kPR<=r)J=lKCd%Mo z%YBfCL`Dr7Ms)(vx1G|VkYNFprrt}g&}n4y!8Y@cSoDDW5jS zF?Z(7nI=Rq=Eq|lNp{j3@9`s6FXrv7l^xUifIAj11)e4-^a(tr{|_V0}6{5 zXbE7R@us}IWp~bl|9BUMmbOGiiVO^DHck<BlL^8Jmi|gKuNvQ31o4BKJQqRN0pNhQVMy!*tQuJ3Fx@X!oR) zm-qD~b{_hLWPz93M?=AWS_URGr0|?Wzm9%d8j{7nL>hX3Imd|v$_BGLhN&YA$)x;5zSiX8baQAm60yT+zEd2zOVCvy`tZ6exa{z@fy$7fqase zg6M!YHju_mY-)Zv9XEJ;WxTPVH z9;t@V{NnPO5t&RYCUm=(L?SMRglE=;}kVFIrhdrH^!g$@2MT$fg7`Lx=lCG5iT=Wrl#h>{ zNzBOw-li}5JR?(yF0zZb!?8{0JdU5CrNTeXl;F&e895(LOxy7dC-T{!Fq(@UuMm}8|ysB&3VHXSX{VwlWq22^F1DW*Li4*Ad6r#4tlklZ% zzPlfXZ~HYHI86D!42obm-d{B=LW2%Sb3@9VYg&nc6oGI&#;K4x9miYdDiQT$!+#|s z4-?93Mk{S{pdAkGcN%5Cnt9{Y?SPTGLx;E&aJQDbGwr<0jZ;-d--Z(M^}%Gnvp-bp z-JNYoFC=S!WggGvY%BXAz2<{^Z|$BMWQ94ltMYou2)G-o6f&uiTE=#r>heyaoHI;Jmjqg^a2db04nW&IX!i@)0(_*5)-@ls8$wAohu zQMiNm=~ugq&uW*QvU(4bY2EW~Ha@tU9Q^IAUqMfVTUE6{O3P47p!kHXP(;(l;QOle zKRwsSytx#1`JTTh6GwLK7r(HUaJ}jY`D$}xqcY)`yTqDkXWbIvH-hPFNz~-fG@v5o zjv-;)2h;cSnaq|AQq62Jnb&lSFz&dS^UHhLUWFyUI_^02+JkqFvQ$i%f(UspgUTq2 zxtiZu{zCW)Mc`vL)pwHh+esvg)2->l>}`xJvR$gO<@Rc@!dawq+9u4ig3vDvB`cEq z-m3Mp31QeN9*v-jGo-s@gM;$;TMdk(Nh?l(%JqLW_!{(0B+e2Z#ZD>Bod zp~M(vXx(D28{l?(`Ile_-*O~2N69D-|Ggl|?8p&sDcSY`eN`o%)s->e!pvK#E5j+d zcV70T@6O1pQYWKdZX<+@>_-`{{ee}OC>wF)zhFtQz;&kBseX5KtsM}b+j{?rl{;OG zJS`VmMt(12hq~{{D;a#ph$namV}4|y+j(cV{g<*}{(X7IH!AmNyh%H%8j}su(?e{a zznoB4t=)BldvBE!x-v9HskF@Sv$<7?Ph>Bm894_c-Vi~Fp3a*uOOAV;=bD8mSA~@K znB3d7&yWND21C%Vp{lg$;ICQ=(#pzJjfj6KAWJ-Rr08K`%SLX!pOqS3A~2v=!~fGW zu?c0Wz9yc&D)jPVj=|X(i*l|~(Y7W^e|*;5uj2gT`NkMdfJONcP_aCyzfKvC3x_V0 zka+|qiUJ-q2se_JI*@-VsSQU*nKSoHU=BAG|g-kl~f8%!> zp1}LwtA`27p-D6OZo?PaAAZa!zB(hrE23;ZEY9)GkdywR(B3aVLscw-&r$Xe0QNA- zGdndk^&NQ?a+uBX;$^u=bm}EE^JpwtPhtwV1Z2axcNR4nUpq$uuKbgcz%Gv7Dcbc)QO4!=j!A@V4 z>b~WhqUtjt`_7EvZjjFYs`#AO-A8%LLgTls$;OisG$i?52Ob*v-759vWt6PAh15Nk z)!4Ub3c2fe!=uQAZI$>T4p`XE_eC!#1Qzeqw!%Y3t@nLdK7!VzphWxUI~sbdF3C+} z;>XT*M?BgOr?~A&Fgf)IkekUU$f}+m|L_j0G_!*}Hn>`QuB__%xNwA+*6D-_9|H&D zu%n8RV;!YhX77`234YFf_b5*;?G!$;5Xcg4wb{%TC&h}(8-aA=%_}c#xf7`Va_b2Y z>JwEbK*S|>=yOBKTjw4b+nWBdL*IXCsOznFfF6P@jS+H(C0xgy(}X#!&Sw|q7u<1Kc3e>rIaCQUjw z{(hl<47#Q8t1!8&gjcI^Ys)d~xjsL+@$BXU(-@3f`cx^`l~ObNv?A9WpYM}Twj9R! z9M0-ApR+VfxD|p0`BtQwe9Th3&c@_5JS?i?4Eo-k2-vJoZ@p(Y;$+;7&tjZ6H`{?2 zNB)n_1eQdjz?SzF0n#U^XWku|Vr@;)A2Cl{Gce5JlX|8yW}#3guz^RmZ<^dosq&@p z*$;fWRyzW8D|$9+(s|Cgh9zlkBkcrXjgTM@xm*g1=5A; zK>;UgCj}Yk_pjyt*?XV0ayupI6=gc$u?EH++w-` z8>r`Yhhod>Xq#@ISMs-ekha)+mMif;-*93o)bdU^4?_S#RraPil(y*ru<@ifGoo^AF+)jQf4Njy=QzLBB2*I_lMF;GJ zua9$iuT&vet9?Gi99m(VG)Lxjr zT2H?qXB4$ItB6ar9bTEBj5Bt-W&3WO=OK;N<-5;C^+{Qrc0v35U28iyT$VvD7uvME zjFtQ>e*;5)6;Y5-F-#M_Gf@20$3AF~wUQ&so}O<-Z?k>V=L|Z1IzeAJX*jTM;?u1| zpp|4?yPTFdT;urF6QH?lgC~^vM+AhpI8zVPi`EGFQ7)Xv;sXImGut2B;Y#n9@5O9K zcYDxt^lOfgj>GC3{l)c4bJsBe#ymvtc`AeuEXl`tl=i=P@ghzm$d9lBQ68@t^t$Qa z=M%lYAh9l1?nkIJXxI-*wvSQWyJYbM9N+fj@hQHRIlh7oCPHYPeR)gP1a5_+!AeB| z{rU(mwSj7qj_8jI@;Sa2<`hSZE(EIU3w-iVOc2=$iIDWK{nDhhBJ0$v-2;WK=gXKnZKFgPn#<)3MylZQ5 z&Gf9cECGA!mdwKzVXX{K7+VuhahvSVM`6<=HcvDPPcBRhP`b%r?NZbOmjnjrd7JB{ zRSyh2=U5l|xZe-k*mt+m_29U$irbr7?xcRx;S%EfL%f*>*Jy`epQ3GmHR!U((1o1g ziN)kDF8d-Y~{?7PNY|D)p_|9ih4^!nImRBKv z>C_+VaH-F9ptT;kiYQimaV7D^wZB>}mV{|%sfU;bpEjc{|F$k!EJohOjSU4WPg4Ll zy4gH@y}z&2^T70`mt)JckN>1Dy>Q@OEQQ5^|7JRl-skUFs{7`mj&1Ol+?Q1&yh5wD zl~k3D$Zat!4|a%AZsB`H9`On6>ND z*V7(GP3vn)PRGl;h!1$%schM@EhaR1q4dhRIUqt}xqKSNqNVOYKEhOGytaz*WK*hZ0eB?O5| zxJqJQA;W2)`~|@a>?bG{6p9w}rtF`5z|Fa>#C6BSe}w*CsH&-%Scffly+dDQ_r*X! z;49c}h%1JW!%-^s_&ypE6yO@&CapEa|1b+gbUH|n8~2xb^l2xlSfL@zvbh#<%9-9d zhAR#TsYb#UY=>}|Ux`orl%+#JwO*|oQ;dV(}bbVxHerdcYDAC{AtTxk7m^FC<_VU~x90-l-|! zl@*ha+rbbY%lNFX_l8d8+pkX8 z+KbY@7A)m7{Oipn#?)IK4Z2!*#5uF~co1w!JoxQ`e}cS5&hnXzXYrS=SPy`QW=8c| zHTt`6;>3GxP?e%U7(Efb^Nl}|Vm3wXs=W*ghM26NOPB6sES1didPnPLqCVCGWA2z0>ODxq%IXuMrL>T8+nBj-&X`qfN3MuyvWEzTgtrg z*!GM+vF#Oa+CPq>*g3O+u9-7=K4$dhm|>DHS+zP|0Ro(_m<1EZ9wA35tBQ_0udM`) zy4J_Wfj@UHO8iwkv*Hvktthaml#Z@SPiGOOvRM51a7IKIzJU>H<+=Y6U6IU7bu{nXK8cXv(2RSvx@3#ZM5LeXwOgs;X0HI*2D2rC5h?1Hattlz@1VgdjTH0x|VD^WMc?3lwe2Zp;-OQ zEK9R;g8Bfb=oq%)C?lx!NcB0h5b(7T&l4}sFFb6_2-_^LLg#dv@Q(_(wrMxckJ=4% zSB*kyReeq2SElBmnay=d<054DE)Y&*Tc;&9u#2Hr8g!9J z1JMNS8ylris{JZ|;Q*21@=_MHxdRyZ23wOYldf^^B@o0^>^W%pNmOv;0`r=lhDCv@3J=y*IO;^YJzq zHMM8fRDYC5&{&w^r7jOcfqpP}9-Zd^B57_wpThQJ3+G}c2)0Z-?P<^Yl zldIjy7)te(49<>mS=8);M;4fd?BDYZP&q2HM`hldukX`p)%U-+&rvl}d7g!D7qVg5 z)?nQ$ZC@PMM$pSH&8M+S&aZZDW*5Y7rNFh(t2dG)50(UJ+pq0rYvmvk4<@Z{3EXYJ zD?ZqdAI^%{2Xja?2z~ml)R%iOYR~bKV5{caUf#W+gE9lxp_(%Gp~+ElAaS z9sfDyBErzys7S5W1$EuqbH6H^qwCF>qF7H+n?^)T*J^fUW!>X+j*baUaIH&}a}pJQ zBP(G%*tz(<;Crg2#VH<;v{`3i5%%LYe1tSaMXL#w_~BqSDm6-IiNK< z3H~&@Xh=!};#qCw56su6+9HBax@-HbY-2m7`=|4P`P$+OsJ^u`^rs6wBIX1t+jLvmRpkT|-{FYZ(pW5SbuOKz-4 zUje8_-JU5^6D{Dhda);|l|XXNX+iiYX^%EWem5PE@)7`au)nUb#OI?`i`5h^9m^mm zVV&IvG_M#}dMjS!HDtpy1)HUVz?8Kffg&`9J^7 z<7d9Erh8feIIf~%-QX_J$(;a%%zFBC50poepZrJI1zc&Ro&%ayGj$>|($Zdj2Vqvt z&zmGad7*LzC+XV%p)bK^tMDtFkrZboI(kpr!d9fn5_{3fDcz|h(Z(Y*I5_xDJ#;{K zygGCL<;r;;`Cb3r!*ZJH48`JzRu6W6?jY$_v;2A<`K&aZ*j|`2JR08x2%{Gl(>FyC zuw1`iJd?Nlge33?XTf^DwE0E&!BiFTQ+>VFa7YmG_LJAO$iDJhUjzIiUSyyzz{7+majeR2BA zPijU;=AM)|{o^jJJdma`iF3wGD@Q&ZeF5K*gywoSMUWq>p)34NAZ6=cR9WMN(-6Q$sl%m-PkVz7t&;)=4;6?glwht~NoG+$>dSAH5&4vOJ7+eXlt z`@$Kz8(p{h1|znW?zH9AqbQ3=6NXre`VC98?Pn9Pmr#9hiyun^f4G-(>D9s^*%JDv z@4+GwK2c`v;~1z3TzMG^u|H;#*OP`g+{nXSIj{3Ea{3ZDf}JAC2l&-qr#eBfmv%a(92pi#Cp6^X6v?8n2KAu?{3 zXf~#QLB3m8v*W4RV-#j8=4LP?fpCYe_>kMGp?HJBsqreJ$*=!J-oKhZBOEjRdh&ut zu&Ny_v(E^x=GG`SFiP(m#WRz%UO`%P)^j)=Z0obp7rtY$CyDT656ek?nNlaJk%Xu5 zMB&x5^RrLmgA@_#3l$P@>Wpeox6VaCs_N-N?Lmf}#p@)qmxi>Rn%Pi=2v0b6ur*Wt z1l8ydnBCHV)P{1>Hy!6{Bc-dsqd#iRK#&FIJC*&h`yYinC^ypG)%jtbO z2>uX|Y;C?FWRJp`C8LgPBhUYRk{EoKxw-E#Sw^~I)HkPZzGTO(#%(QveVX_j_U|`J)l^r< zjbgmL7fjFNPUrdL`-R-7%z(Ut&?#2dzQ(6tZ!xSgm0GMBNy*ZUf*UQK)yUmBOQ|~k0&|`&v9OUKen;EfJ*ZF%Qy32cZr@oq?!Zom&R)s3D+NYAAvUv`F(i*ML08Hn`Fdsx%jDOd<7wgUZj@{Wr2aZpYf_GV1`kpbI z)QuW9x5rTP@pacP-|1p?X6}`ul@L0JSgzV(VsytCVuQ%3L*${RG(Q?&@S(q3k<<59 zO8bYhF}M%%&Br!dKFTT!6=}39==S?7XtApjXYHC;Zh36d<>54(JtW)nUIy*1el>`B zFE5KBGP)l;3rHB?+fNjcDsi$vSZ{BBt(3|2VM%XJB;%#NHES7bc}&piI|kF0#!L_)hrFF%(j$2CI`;vMDX2l@&%_M&swoFTx&pjK;dM37 zAnIfZ(meage*aX~_WZ0OPh5cyb#BZCR2Zllk@{a!`svE&pokGsFw2*?tpI|=@2Ao` z_e#KD3OX5npqbKEyc&MZkdT6ps{RkqVZ(V-O3YDmokv)Zu0i@c$PJLcj$yuJ?--p;dr71dB)*XSfP{ z^A{OLhxM0qq?hW>8|FOU+eMOua`4FxCjdCSc##EgPFJ9EzM!XPdh+DWylRdcV3Bp8 zYZ^e!1mgY!2ei?o+$WL}(|WqPT|iOR2?RgRTDz?G{78MA)Ywpheg(NsND=JG&&ml} zocn_i*#VXpDxH~7AhGYAsZje+JFLME0TU9x*ypVT!--1K(|$#i^Jk8NYPSN#hXkPw z+gdsWtyLkP^o0;3KUL8T3i|seW%YZv96Wx!2NMeI-;lG)2H)laZgoCGD@#8~lMsnC zKO*>fei!#y3EQsJ;G(Nyr1rN@-2CiWf!k#MtRnYIMv_n^W-M|l>D&k zC+{I@?`HZ(l}SFJ=dxR!6#zU5;C6&;1`wP!@`g3bBMN~-cLm%MvimJMoIjVh|LS-@}NrdZV zrKMW|*|IOu2sn-G>mv~c2H?T*O`sv5pu(`(&3yY>fi5lrYYLtibQg6%ThRej!D~52(;y!uS#RUUjde<+Mj3j_w=vp@K~u-ED=c!wXdL?6 z__)Pz04z-;V0%*P#Y3&{Y~nq-Ab!m2WGJU2>1k4u9V0H=W>`eUy%lioxwqDDM&!I5 zAuaO{2@bAA5Js)720$-zx`s<(hTDfOHQGsjE?a|-qy!`;qQ|_Fd$HQk&;cO!dv(qkftxZi4CgEx03Zr;2ZaqHJs*);?>$gt`;&Ay+nx&Fj;cD|Ku z{b1PzpYN?gdpqzI!7XYgu$s%$XHYS3xaG7&MYYcv`bl}94yslb`Z&O0#Del$pG|C1 zQa+JcZ8cmM5$#|hUWq2>#i@A2A@T!j@!8>M&s`SWtd5o~I!S7thgFpD($~?En8rAK zA6|-V9lTB^@QG_4LLqc*p#jer8SSSZOVwN)$1A32~6EeO-7Pw6%w@ zXyclf=)1}0BQGw-srhD0B99>>E6eSo9{JzzRn>p3UKARA4L||H z@krmeZLi=T)A0Pom*4%O`~2`JKsLg!TVdBl`X6WjzYwbZKvM8)xGodM2jHOOl}t+v z(o?8eE<_}Gco}wclU6;vpA-tX2G_!|Kt#|9tsr>d3VJ91MK!*uZe^;PJGCt?T~t8) z-_d@^o&&XhYUx0Tm1pJ5Jw%HjLXs3biz3WH-_ksA`- zkq2S2^E%aX1lru;0M{)#55Bz>r-`jVwgI_YN4jpb!wXWs%CeY7;Cx!>cqaeA`ms0DL4gPXWajw70b8N%U2S?%H+Le+ra> z4`@F+Je&!{(_6Q0MG$?yOsWkuP5Rjf1qPamkYfn(eI<&0(3TmcwOR(eHh}$t21rR1 zFzy+X^K1xcvb;z48)TgkkYpfhA`RZXokIEbr`|wB&E-v5*)dc*$oB-cnkAg`L_*sQ zh=}=Gz&If$z?fDBgii3(ff4m+H5HfE-|rKULjeaizd&9|{-?Y6U2MI8^7#8V|9px4 ziPHb^%m1!@dv+QUYcev@F)*pFPD_b2Wv;h?f;qf5qhN%`K3h+)_3_aPKdRbXMa4*$ z@!KP~)F;FDApiH8s%%kTymiYqzX|ogxqK!HclGOQWdL;8hnhN7Y~42NQ&MQ0q8(wV z*F57!zGt&@s(z>`P#~8vz6OE z2^qC>s+8cIyqfWtN4v&s|E3WAT)NmX3KG^2-*N$)iBPgm_)dXF_NnDnwVu|1-r4!F zl&IbaSroz|YzsXy_G`*y>l9ISKbNKJjahtGc`1!t}KdkGnkwReveZeyO6K$!SDrp#UJng%qn` z2SFX?yXJk1AiCjIwNwYX7v^@nQD2CEutWIPEIiNa(os2s7U~vUYGr?PLwAy?MqATp1%0@enPuDv1)AoHnk(?RES|R?Km40&m-8peb(A$)XJm~w;bTNfZ+vt%cQ@69bsEQr(O zvN`kkmI(RTPno~2%-nUY>m43(9N}<^nDYPv3m=X;q1tn$3Jwh*c>6UvU*9EC3a0=5 zR$gvn9##b1_Zo9w6d}!2 z<{R`GC$)9Q4sz(~oH+5|XFNL;;cXNX!}wQ8BJH_A zF=KXXoY*62OQTIRC%NuwED`C(mynD-lrWTEwa~j!>i|#dzh3p*jooEVIZ#6IAj&U9 zD_qPu^3?A`?VNQtoyL^-9MVL8Ugl!2E+LOGMrGUt1S{>z8H&qdT@LZL>GR>_{I z_q*c%7g1JerTPUQT_etQe37-o-GrtNtN|T!ib+bEY}EOu4qKjzzdYRhD{=D?S~%G{Y=wk`Us~wt)$&xx5OW=h3iJG8R5ew{a_jZWqSrj>q14oiynbzUM ztwU8cOQRwh({I8v#rbw_sLE+%#f9tHlFVp_rCo26)>uywZ3VE5 z{wr1Y+ZE+nn06Y6buCLxWzB-^m*)moVg`G%t)i$gNBG1JFH|Xe-dbh$^aL({_Fl(b zEv~|)VuSodxSESCyO4uZHJk4*Ws!bAC=)}&*9bc=Yz-MAk(_~*DSwFCVM6V@+Z%z|+T_NKvUB0b*tD@YbY2^;YJW0N zQ#22SpjCrRfW@y`Qb(H&)0B!%rl2AWc7M~Lj?b& z0noh3>J66}ft~} zI8o}C=KqM9C2oc{xHeO+uqQPw?fB$%&5-3XoAcN|FqJdsh%G?3A9wi5`+TZRl|R$g zUj69N_Mzh$dI|0H{FrML4JSCLuP!gMeH~OO*FC5PPxp7}&U_aW#MH88SfVxX zrzIwWg#BQs5DBMo30iQWMhpc7Sp3RJq3Ht~$NbL))b@K_Y||0C?KL5Je6xyFoD7+x&k4% zKtMF$f3m(B?&IfAtE@aBXNTD`2!SQx@-0W1 z`LM9CZMHPE{dF_N3|QcY4<1|sH$*S-L>3Szm~z=nRnnf=)GfRByHG0wSXCx?NMm3; z`pYf>2L_Ul3tX7YDy0@yHV)O^NAd>3CvJE}kX6y7$=99hlE>Yqel~4G$-Rf7tgItQtJU0Im+96acyE<8r>}SF0{cpU?<}#iW_1a7 zw7p{wD3c7QW;hEmY+*PrMYhZLU%$2o2d^D@&(S#r;f^G-By8I+cba`Gw9nQX6VoA8 z8Tj?Vfj#^7<&HGQid^vrxwZ{i8rf7cmks@e7Q+QxX3apiZFO+@JwDNF$HtiP2L}=# zOD3EMFjV)OEE^P-Jb2{Dr6Q*$Loj|Sn0}Wq3b^bXkb65C%ef`73)tV~FUax4?N@{T zrGH*!JkYKq_>KXXj)>;*nwHRN5*=cokR?02D$b0%qi6$ZC_GmM{jrDsSYYfvXF?>kg+Sju zg8#uJ9d5u>{vokByE6B*SmG2U8ZYeY*FL*3ZFXkM;XK|guJ|3RMIUB!`EHM7@*Sz0 z$>y$sHwTHUq&AMYnJnZ7Jo*T#q@_GYWhP%2@zrjQ9X@Q;OqS~sW9Y{)uqIEP`yIn- zmFS4bo6e>NhTdwppo0#M+$(1})~wF#Oz@{>L8b>rewy1<_*}YtnQ^584?VCj^1YFm z8JNH*fdA-m65A zk9#7RR&eFKs4ZJ~2>)U`cm{v*VNfhUNP+sJb925zE1Yo2EX&K*B1q3H;xHVyZB&DB zWM}pOMD!Q;8&%b9-?FWwb4KS^JAvWg&2AI(dHD5}6E{p+5@zTBN=tJXzn?~{c%X~H zblo1wc2l1k8AEB2!-SSTn!M{|3Cc_7ylnT$IRe*wsAb!!{pMb zf+C$$yE~8M-FdA}h>aHs_1M94^31fI-jCCod3Nf-iIr>Z7p3q$-+(znsBET$&LV0v zjWWsv5wy}xoy!-ze_s5K#QV9zcaRcBDRZb^{c1%~nHKY)Jf1`v(7m?&yY3M;%UkQa z7v`_~`yGE=tRSUZBXlIIceSl_d(K>M758ZI0cBm>o?W|Ab2x0jh2i9#MJsbxS@*Z- zk2fkONoSfQ7d67Ll}kSW1j!H7yc-&!z18JrgM^u2pT}#<WZW?J9?W zu!6^>^9Pps=6*@(59Dsmpav`F3mPv0?i85GVY+?dUu~8jFEoQhQGU%LX>qxYt3WSh z4_wNBBXUffDp%!0d7PufRfrPd;z;g>pR){+e!`O}=l($_oZP)@&sSLmrnk`_v5X2s z=ayqc86LuMG$wBr+g3+Q{!Ki9;Bdj)S!cli?UeW02V1~V#XjKH4Y;ub<|^<=i|oyF z5&!rTH}|JIukqC_^cYcPDD5`MEpU0?qlrDE zle52%)1I!>`O&%s14R@IOGL0t0&Ff6R&Y0W&c#`k?+buR)zhtK5s>ILR; zna{fdlQc*09h?75uo1qg7FN2=G-|a?K=U{GY+3cQ$B7%Poj5QU{HzWjQc67fvxwq? zbfoRlrT9ld(B<}~sIl~R+*Tk6L5K-DjhH!CJ5xf7<5Zmu&kbG|5FDgULKlvg(2w{? z=@hWOk^ffbW@je1jk-d$89BAD~HBR`5utzk=? zQe*hsooQz33CF$9Wjt(vU6VIh<0A|A(b;Q*lh@-mI9C~Y+UZx6gK4_C?ML1LIzyq5 zJInGMpFHZdb7rn`@kR#R`6hZuHuZ;?Bmeoo^YZ@&bI31&MBo@PY|}sEu#q2RexzcB zI9Jk~g~)_|TXfFrO&H;Cj)Ue6<} z3iTv=b*OeC>~k0QM+1|BaPI5Zr+a#O>S$1qbdEJv_)qb{*x8J+F&APBRCB%jP;UcJ z`ue5ZePUu$lemeyd@!QBHPyr7gx!+%4ixU5UZSi2q)$NBMa+~NW-g+y{e3W=`^^_+ zSif4^siN7|6J?;_$&k)1@g)1(O_=w}->vg8A=5Fweh<1PaM^1JnCE7lw4~&DI8~Hn z^uknQYhq{dT(wxNYM+)CkFXZPpzz^?v|Q6H6XD}dOHTg%thRO|g+l2WS?7!JSH8J& zrCmWHJ2tP(i$|}m+G$G4>=R= z)z_$SGC-S8n(b9lxZvKQk-toq|IObgNA#iMs2j0=kd+NgqcIEDyV)fK4xXYK11imoMVgQf$d|wutjvJvl?sk(l-uXE`1JPoC(=BZhi?C3PVY9U9oEUpm9C-E zI3-&ZONtCj`$W|%(a{Aqmd`UfM$+7dhNMtx3v=?r=8Ml}2-K9u);2eRfdS0G_^hGC zMdlG+wl*cyp6>Is@(f!Uk- z5uunH^Z7t8_*9a?nc9{huYmV!5-PIj(PHM#iJd)ANI$_0@5$}|GVjKXN_F>WCDL0x z|CT%mJ8aWrvVJ=HezR`A|KWhD0@2^7dTDo;WYnJEL1c-}k0sYy&)@Z%%x;aeiC76D zhuHfkGJH)*NB;3Ug;N$7ee@^VVwZx0m+$V_bnFyhc$}Kz(tz;fIPvMG@7zU7C~k-) z#@&iYY<##?$)SBa|30nPf0x;ArFZLkR4jB6cbKa^WP2{Z8+%{Em~C!R%S`?>rp6o} zP@GM(uK(~M6Dsh4y?J*3{{13xS|y@+Z|*;6KPQZ$ z{bK%k*GV&8lt;$+)U?iFdDJ@(`*22X)o0e$${hIoh{=FI-4%bb54nO12?WZb=b_aJoKtlzZV%kQ|$`x4Iq%myk{ z_&T2+G%{tv(~P7b#v*8 zGzyW0OD&bJ_KMjytOjJnEZ4ZwSW`gs87_~Z7dbNso&A3dS=vWT!OpvleS0BuEXLKE z?y`bG*OzDH*VJ;6{T^t+QpY%AY60ojzHmO?g-3T83>(L#ZVatNX^$9Gd~`m9SotK^1hwN|ePOqI>jJOZ3^B($rUOxL#Q;ckRTk_wl0Z*Ho5Di=sX& zx&fRYd3h~;PipDvIi9t^*XQ_YvBj`8fl(Fty#a~U>u|=*%gS&Pev#z^tS9(uMY#AtAG)4yAPUVbbs^_ zKkAe94b;*zxRv>tlDxko^4B6f_VrZtbeE6}P1+u~lV*RwP2^$EkWK@`fj51o2JsyH z0A)Cx7=EzCgIVN6)e)Zg&{!8hYQCmWb21|Fct-Cr%v2&SRWklyo99|%P1pOJG}4!# z&v_}mesR;o<3W?@i<$#~Og{bkY6K&paSiQmRXdWYx&B$uF`N7T9!Dq2XD38NBOTQ> zg3okUv#BXevy7a3X6p6ohrd-O?fhqvZqm{Jq&4JA;!d~1xIEL!ncSJBd)jN3=?_KXwY7YHfcf^frIM{hIXz9aXF$)MGxG+MyJwG( z99W{RbaT(4A;%517Fm4}E1{QfikuKaSEIIIaaGyGXA4GXPH@~|j-@5g3u%O)ASi!I@W6u|6w{^DA&Bkaf*~vUn zFLo^$j>oCqwAG`8fHS;h+$;9F%r54N?(phDf#r=GS!do8EZH+?T&hB1e5#l#C5>fL zQI55;yAoamrXO)!z<=-?4%K1@*l>w!MmOAdjEL!(O%3^A;YaZMF3?Lp=Fz@eS#U}^ z%bQDmMLlKF1`0j?H?3?wb$(@h<%%$6T;J_GdtiG>uRi9iAQ%^o zd|^1(h|w7iL65FbFg3oSlg~U`RNha)QInQFYAJW3vJ>n@cmZNzUURm0u4jfg`&cr; zOURhL-Z?iK#7Oj~)aM_})O~8By|9$Y>Bske?AC}+VPmVWa_pQtiJ(D?xm=iynW#E| zuH1~C_9zcc&P!5h9EuzI@qy*VkuVLcy#3mhbKME?FY=N-k4&GB)GH%R&4KzOOivqLT%+&lSW_EuN|&{#Tb}*EGW6;bB(m~0_s_k# zx;fH-M0Ft0+Xlvx#byUDjyR;s9DZF@x&BONze9WLXT@h;TxKydW8~rA^fXf2HMPV< zLk}AUqGxQVzU6(yY0-S4-_g5O=*=8SB8a1ewC1?;M%%nDU;;QB6j4Zcl8d?)G+SuTW9?2xuyb<0Gk3yU#vb?%=hrp#jz+E2YrweLCjW&Nb!cje z^xP}lx21HgxhLxSC5t=DvR8qaY3q;8us)3R`#_%ffVC_r4pe)T_;QLZx!cbl)Lm$F zyjsv;*a081PExNfjIsUamG_-~>SS~mtSY0WCZpkDVW6G;b#F4_Mxti8+xR^I+K}-R;s5=81d3fd_S>uP-(S}=a_lF=De@b65n#fv^Sge%5Qe8Cyl4nx zTVYXAM9cU7qt6F_LP_CTub#gnBTKlIFha*UcEih9sI(DVhK7ck<^QkCy!`!3<2g%^ zeKG_pHW?Y2mo~x%3IM64lkgqOOLGxeAijeHQL}v0!Ty&v-#_8^FJ1>J0ki}TO=~Ud z>({HOqql3pCt@-B%m69p9;gBvAk<-v{!efE81K)9CitVl!j5WekjCsM2>>4Y|3AcgUyc7wogmll zfpOH=hU>;7)u#;f^df=W&UdW!59ips`wzkJ;6=r~kk18}n#vdlP(K6=#S+#LAQoN= z!%AEKN1R%g`~T_Y;2Q1!P42+Qys7iu=zd=(_);eMvq$A-V{d6tjh-0HtY?Y0mp0Ee zHZ~A|Cj?~(&4WP5M4*4z)BmWT})?0|6Bk1bNR|rXA7?*%s8la zXy1F&R|B`eau#S0UBvT%55a($6DWOD<}}i@H{O?&1I?_^dm5+ge-6(^SaRw;S4-=L zk6ddLK2})+7&!T*xzHL10zz8>1r8QprAJbRb`8ewmJg)#y^rIJkNFL?9cQ3-F{NCg*$Cc?0az~5o3hH>_rH3IqM*j-qf!p}r8wTjgkgXA1^4{>~aBH(`?C zeQW(S52E5~f+LIU5Qix4x1X@rn~k48Yi1!>xhjGoJG*V zP`rO838Wr`oB*JI@}oJ4HmH>NWAu)c^!d6N(KQf$7idH6y*m!17M*m_&Urq14vgu7 zQm=p#sFb()S>MS!m5%=u=C>ou^ES8w55^R9W0QgAiZ+x zWff`CK-h!8!`9vK$ktm&4Lxsn_gt|GU=16^?6a95Gig(c7He3~0=P)}nitG7P_696 zB0xLkfjqOH%vP+4fhx<=8-O>%s(2QFRFFW(4ks=JZ?CMbxmMHvG8lHe(OpG^yS#n{ zI><9?g)Gih0dq!-Bvfxc!IpZivNV1`t14L3ot#0|#)dD)UN1G$1nVVrRN2^C@j~Jn zd^H4li-YVrDkiJ5bh+5ZE~M<@{{U&xly#R2a)*VfbW>hpz~3C+$&@z#h{qWjw165} zGhb;%9o(Lfv*_~j@+??D3vI|u_MW?^4m4Rj@@Rm-9xbuIdiAA^Ui9}&3341`i5`y&w;@;K48Jxg_|m@C_Hmmc~lz zbZfYFicdD{S`vDG{W~f6N}Qz5-w4XD?l_z+K=@@t0ntrhx9dehVkHbDdJ%vTo(8xK zLia;knS!cI1OrHAVCDLJy$6EHyhz{pk3yyikS4*7oX2sjDYY1+5~+6m_r|eo&rFa{ zAv?i0oY`7OzOuLMpJKinX?Lji_;jC2X5J3;^8~Lh4_s=57WP%ilc5H+ z!2a%7taKK2I3YhG9_PFG_ehIz{NINmUK1Qr=Xn|Rlkydr02uD5%424D>C&soN$(nj z$5V}%y8qU|VPwfblV0Dq@eR_#zEIa?HD5Q!6g=e)8&~1nAPVS-XOhFAcygEX3Ip1$ zpG9Na7nh+Zp;GZ$Dhn6{Q0;(OiNHb=b#mCLs`-V1QCa9WM>ucbp+Wb|x6np~X-!Zi zgl6pgnwG`bg3&T%!GCI6&2*$T_`dI+E39JI?XMib;Q|N8tA(NPL&F+`M-KqiHJ$+w zBxuGy++3=6AJYhoC5S>%xfH2>U(^?C^$&vP&Ds;%{>Iu4ia9-KctVaQdZX|9$oF-N z(%I=m{$`BI8m(S=KwX>m9{KjoR9y^m>Y*(wIlDM@c7<`(=Ec??f4-L=*I2i#mVNIw z(*1FB-TId{ds{F6Ai#YQFmm;0Q}a!o0-Jg@;3ll~Ha%o31vO=juQWqSHc>r z{c%*1J@6DSybM`fX8lbQOU3!azv5nw;C2yGqa3bW2 z0I@HLvcs~T-M)Q$kEo~|WHp^*H+Oyp3JPeYf|h~&aKxqfV(j(gXM@Arv~E2c+ug8G zP#8V~P49s-S>&gH_k%Wl!nR6@UYl2dM>{tbRBgM~^2kqg7+3^wlEA;zt80OI2G{){ z1p>tHD^e?^B&FX^=6cr9tt!0OO2t7~BDfT~{y+WN)%Vw3kb+wCdUfunYsBAs+w2{_meLm5Uy!&=n7 zm!4)uZ6nU@b!%Tg9Ks@e5IM?!f`@z<*nAP-CG@gCmTXGWvcn-xNHvz*s~g0pwD_f}o1S{mei``vr5z1FkRvkiIk#r&bzxzjMT_BuPS zr0As(Gk$xU+j6Kthcu)WUqLA|bS;4j_dLvuKgQR!>Q0F%SDeF2@(IHb*iNb;f9zaF z40;mCud{Bexda9@0QZV*aJug%1q8~Ehn_e z+Sh5~*85pLeEW7TRx&chA`WvgWT{pm&bhRT>U!3v!@}4ru?ka;QbNa6rQbv*mkhsY_sf%-u~rh#xJjz&oeG4vIX_Zii4I3T1PPHS ze|OPltkd*~A<2a4&ZlZ&<*wDrffX9mLFbp!b+r>;>t&nib9?zW2+Sc#M>N&jzdhWz zQF64@e|>#j6#6fk?h6Fv33?)EjS0sjrQ=G^a0vN)k zRoQ)62CHmxc>yLpKVG#G8%HkO0 zxSNQW53#2QO|Y&Nb6jzJ+8)sMbK+J6-?j>h;m!EwFP$Ur2g&yfE$jE776hq_={$2o zrKfL}1h}`^69%{>tVqGpOS2VE^%qtRC{aumK6eF8pm)pINz$wgYI_WcC9Z0MXrdvw z=}fbem?%G{r-LP1*@niDg_-%bDDbQQuIS5E5CIwedzh3P$lMNk#FE z*yM=$^^iBAp*CK{JBI}6BLrm?k8aoHO~3eQKL-Wzs#90t#Gs=#2al$@68W!Ry7US@ z3PN^I^(&TS_}5p&0xK<|;8%erBV?aj$BvyJC>!&MnB!#@#l%WGcR=MA>NDlxF=|jE$-x67ipoYN z5-m?3TvF>e(W>6FMB|Gs6qMU2H`;J3hSZUVarc+sUJ!tehz;;02H!+FXU4ete&`=NDc6WA8mKr3N}3BN63wPCI?R=nVH%T7eov@mX)sjE z=Jl+hvSwt|sWVQ_%p*6tCp&ricXTnDVV|vnZS79h%LGIh$cFe|R#!YSl7k~QHyTu+ zM&XT5LOeX$vOA&R*im(>DyT1w7#(W41{qa?hPQsmgXV4wWpYg`&S%&m+=Hm>|e%X?8ajfShN9k zUiq=K-5%x(w#YI#^U`*$O{P!(5!hO6VrRz6}e;%?WxUbi2-=mF=uij`!i(W~Ll zsO3dQ#PZMO`05WjHsYsvdG%sVOagKZ@*mu71^ZfifT$Mk?a&)(7z%mpbe{@&O-P1$ zOoq8Gb(|$1HtZ`QxIF$cS*e2eiZx%KG|Sp>4AlsG(*XO<(RN;spc=yY_AgzOSsyly zgM9?#zd5S8?8Mh;)X5L*JL_@SS&ApY+x4MPw%ANKA09`prb#&aSL(hD&%7teu^w+B zf4AZ#07*6<>Z#_H&c=|WRr+SMP_oAbf?Hsf+1o?>H{XfbNc2o^Y_pU^H8cOoGw-|q zXL-oSu_a*qyAgo}`}?*E2k;Ed?`&2Ys@U_|z`Xe@wS-030FZEJUvcc7N~ltI1?I{V zlY;}e;@P*7moM(92}uIv%y@Lj7>I_pD0qY%-xO!#-jUc{&YTp`&%?_MIIAkG4L-h% zpD*aaRBQdibDY6F87z3E6F#e2HW>AKElt%G6gg6KO)|Y7d)R!L;s>^+k_=vOgs{Gq z;=mwuq}6=G)&`(a;QX%NiV!0|tOfU=gxBc<_MD z$F^TDI$OIA**xy84O5)WEq-3anKMv-D`J!*T)_l%<5=!v+Oz3h)=1|9lIl5|>+Iyz zSD)`mE-TOJ*(_Dvdq|+jz=W2l zc}Oi}wru*)$SoUxFA{}n`MoYD&B->v(P7%f@Q`59uaiMNY*hQnf@Xpm-UnijX45G+5bW++MA?|PT+$7Mr(uQG zPFW8hVB(wGS6J`!ArdX(V7m}bW8-B#%#d+stJN-URdR~~QvDUDOv=m3PQP=g0I+S- z6VKHN8pUoXU)!LBBtGi|(rfq^{VNw|8&WDT2kbzfE4>IqbUD9_OdH561b4EtE4?eY z)!G#1t8m>J77@}ZMiHhDp6eN6E9BFk4a7<-9}&BLu)9jVvi4VKH2YVlsz4pMtEeRl z?QH0yLt8yv{fl8JG$gT2>jH_=n*y$}_xj}@^JgCb-BYaL3vIEQS2DD#9XZ1GpvMgR zPp8+8U}z5%$ay&BXBj^LBGed1&8I{Zfd$?mglY%OmFl$$?Ag7$Bd$yI#AqD-J8MYN zylZf}_|Rq-SK&HN%mdTn2a9I@;FaH#U#s@lV}Cw1N}+JDiwU?{w( z6IeUeJ$^#QZy|`5(Ij@Zb(}xD$e_Q$R(u*5eu1lQHrwIS>=}=x=??&bH_miE#6D`9 z>lyHJa}M2ICioOeP{b_HEG;?{RtzZZyf2HOio&59d#+$}{Vlhe-pU3ws9i0mB9V?M z&$lh?c+P_21WR-h9;+y5 z1mB_7%UE`qtCF72-MBQ9a{01N<#<#EKi%6FUrf{UC;(^n+RtdKZzFiGI+t$TtCT5% z4tvKcc*cUpT`?at$@aA_-3jFoQ*a&J$VH;Hob;hvItV}!{@wCQj7s~XUk-XY_3$KUN^!-}3kfi5SyuE7+>&x)7nRf31vEHf9`az(e(VAhAzGh65cFB;$WDu4MDyYYJHsCNQ-^HHwG>Ak_T&`4`a0k>l%mt#b*kXY*_oRqX() za9l#7@l4zopWWZ7Ngs|B-Kc}2?rX3C|Hv*^2YlXDt6slGrO~^KdI^a!F}HY5F8x&t zS@S?HdiRfbxo=}zrh>wU)YMDJu7J>gFsPNaJcB*a9XCukb?a=6N67Ae>x?9tD`1wJWW z_i>+L$_uI}e-e zXq->u-|t+sOAOpgmO2I{;(F06#l(avX9ZbjLa}Oa(SzKcl{v5^BbvsiBqehnD#$_7 z(Tb^Gm^PIj@Imn#U_9kMoEAE1{n|5pY*M;V?qjCtm)+F?%Ki;!RnPlsH%ea z+P};5@71frfzvM27J{qmSucCcAi*NQ^{7d!Xw9I9t` zh2HJ!;Cxp8^ML0%zx+r~eH_Egt^J}Jeoy?))f^9F>fcVGJm~CCAON1;(ftaZE~hCb z5jx8ItjO;_V-w{$xojEriKA3$8HtWVWhFy0ew0_x%fjv0s5z5mlKZ z)B7)OdUpf72l+QcXT$gNQb77D?}mAZ0@g4q>g!+Ry2~pdYXZ2Ms4w#o7BHX5?5qTD zPRpW;U4J4Rv4HE2&gU;WPZqdyTM(@!3=nbS&+3UWw94Nfd|U1X9H+ILP%V$T!Q5{? z6{;+wIDr``qCts#AyyuWzQ0(t0}nuIVbT={Em^iLBJnF-|0#?S#g3FiCb$8-9q#q5 z2t*$VJ$R^&e6wpiWzS8;F9x_B^$nI99PJGoy*`9?x2cevwAS*jtK`;as&f4p9KLUfm z!=H`vDdAQF@Sqd7^*_uTWs228>H!!mA-|*d4}0kaO!n+ML4{i1b0X0DSQ zZFNNukq3x1_D(}wArDJ;;N(=9Lu6bD%0CMvZ$%Zc_p^PxjHbvD%^9LUuo@^$+2WsF z3yYq~M$LwK_%d;b|kh0C-5aBuk#1&$Qxgw&5sOgzNIS$;<@84Ud} z#n!OoizFF7x*Y^M4f0bE^hbd!xUfwBs*y3m;y7TX<)>rmxmtDpdA({O#o2^AvcWnz zn|M+!L{RQN!HY!#>nOxl`!Jl~qpNlR?_~-!S&7E+1JyoAjODV4pdKv})ol45{K53{ zG5IF;VaCo}-Qqjm}K!-9)r#!;LU`?dSurD)G6K+6z3JO_DN4X>XXw(1MA<%xl61%LH|3IF;YOD#w zHdf#VW;ko~MmTejVbPM4lWdUJIT!m^ZUoDq!FJlriMl`=XgGv6eG~{<3jdArQw~xS&-a3(#SMv?kL1k zQS%bZpK9SuHn`I@z*#Szip8JwEKSx#=eqWDsMJU9w-=y%e;Ro?+Ur$%q zy~SgTf!AnOW-0u<*fV?)WY?^`?)(Yt*B&&7MV_0#tis3>#o;j-QeXVY5{gQ}CPB$L zygVdf*a)HF5j^ zxF0Bo0Ikfp!*#DAD`kSUb}e$wA}!v*2DyTRmN-6F9DWtQX6Bozs1nGu2vd9XpF$we zvFtdA(;Sso(^#(G%S1&YA}aU8W+l|;#|jUE*9VG96!ADD<#*&;6YD4eS-qtvYKoQShc%<2{oi4Y0E*^)l;aLP2?Ff`jOkqiAfIsREQLeFc(WT(BJd)$soEIO;$8 zr$W@#1wANy5gWySE#B&fl2|_`=S2)fdlN$J;IrY>h3pM2AdFz8MwG5(KMr|d;1>=z z-5uAPGiZ909iq!7)%~{N+^7Q)NTE?e8qVrKiJOVd*`owi5N4Oo2t?hQXl_&4lgDur z;#-dK18!~}hez~fD(z%Svy6YqC0#9HOchju72sAYo#mR~g;EV{H#94u<845ZiVlIF z$-vO}ljgIOZ(6!11k=0t>UFOrrB~tfKM9fIXqQ2cL2z8y>%3Y|%!MbRRA#N10YuhP zQC2v@C=a3Z2xw`m{n?VI3%S}sGKF4Y$vR-5I0k|<$~9pTLxq;S$#x>=_4o`=lx~52 zf~?~dMB0$r^%J`((+^o(Ey$}_XAz{c!|W0`4z-sLtg;Fhtw3J8)@hSkSpz*Y2B-}N z9&-X^snN@FTnI~jEm_L^57Ey(e^iA9U*9@1@qZU{{0$7eh#+FcmN95!`^JOm$`cPD z4s^H3}b7y2RTJXkab7;9jDKAJBqoW^Ci=kFyfF38*%j7`p(H;&e zaI^#MgswonUL*Y=U68@JAu;3~>u3+MjRpi)XHl=uh^2W{l0=EHY|7Lk5>4KCez#$u z5Q;dHBQnFeNBRLSyg?m$ivd7ElB6)?dY%eCFhkpepQLEFqU`GCVC4es$3e$68_TNz zX-R|p{aeW?m%EExEwI`5R0kG1T}*J|6Io|Yai8;vr&qw?00|zvZg7kdNjeeCFg!QP zZ1VzpGU!LrP*l3O)_0fAG_?*mok7%e^c?z?(RMhq>W=2x2&NqK`P9fJOk84Ja2uqu z&+zjYLPf%!J-ge|-v1F6q0<*A1^ddxZod41znz0@G{r~<6tyv>pA2wA%S1{U#xGpGv4RiOA@)(kt7t}SE2xOKqXy(d2uO=%(E0`^WHAAmoo_i(n<*w-QO zofQbL5YGzAZa*?tfflb=ZTDW6LBWr`Z|_%D)!CF=05LM&TctGuIH~Fvp8A$|QEZEz zwh)~%i)lBjxwmA1^0WBoV=`<-miB}*G1TOoYLzoCnK zKm1gIr4^7B4RHRT;D$M0nSB~1?=IwIU~vagCTuaHHBJ1f47x&;=U-+y4lFzzNMhM0 z21~wG+Mu>op>&JkKWmHrmvd8p9yajt=>xm&*1jRWmYg02FZA!p>FhwBK^&nv}*ylQ8*W1|K+}xjxT7>3}FKzsJ%e>*NyS8E9gt^5UW-ys2OrAn663_h5hUW92h~)mNj%$!+g> z&ZcwF@QG9@RNTNO_pcG&`xDx{jAE&eyhZMY;5X&ctWex(TCN4$dgSz4C@|f+bZ`34 zN@?;A=NB*GTvQMykDtQCz#ul!Eofw%xeBVqrLsWnli6{{+s2r(@%@x3R`UPUj&_b; zx~66#xg@^Vm?)dEgxOW-j@Pxrm3H=WD8w1GMHeW|M6B3itP`Qsl~{N6)ZIk`a6=k1=(%S}g+ zh%wx&k4clwT3Fv-OLQR(NMX4nOlY*xO*s|kX9V7DaK_%~gNw=con8dCuFLOcusj80 zD?O*#@DQdN95S|4DQ<3PIV+1vuhyLHk8_Vh=PH-RB}Tft#Q(>~590A~ zdas#R%h1x}7eS^IS9olgw}Hx;o{1D`z+(*~75IdgohJt_Hb*bg&Bd>G6L@kcAtnRZGgU+8S*tm>WgY0t zi@q`&$NHBvgXop>%5b17L)(+cvklinLX%-0GB~i1_K!7;YfN9GB~b*uA7Ah~z|M7= zx%E(s081b=C5OWm3<>8O8a1Z-UVD)UPK5(P-toUO#Go^yOMk1VtaPsHlUdrVppup& zi1AmKKXAc8*uITTuj8v+Ty`@Ei1ZMiUQkqo=xk&9B()w+wnoQu7c?rKSpIS?{Q55p zrSj;0w|*Pnxy|<_IxN=X-ooRlj-rfT^lWQXhNPcD^3f6NeZV(Xey zpjN*f2gcX#w?ZZlrn5@U0KeWYX3p!tmItAbdy&UZZJV=s84z&&_U(j$A{*YViiggm zIT|&?PUUxq+e_wVyEHp*Q-hJ+99! zf9=3)sy{fS8P1*A{j+`j63@Tdh10lyQceEFdI zBg03)?_dyr?1P-QsgodLmm-Bs>Mr^PVY_T_j&%3?RoJ}@wmZ=dWav@{5q%{L6pQm= zKJ>MdB?XzM8It1vw;#_mw)IR=ThkIz`Q!4%t;?O! z5|eth~WT8f17M_#Tli006nLrWvw8GJT-7_wrvrXYPkZ0o{b6#aZo_he`N?JB|G z%l~m}W#UmDSKZqE=FN2iS6l{#(yrpe56zm>_@S=TREY_yMBzrih;abVOSP%Wjf7*0 zi58AIhdMWhLoNzg^aS*oN87zuk1mcLG?w!?RQK(%pIGU}nzbbjEYy70e!3x!OlUT@dzbHHVAagV~Pc^RQBv_QOoKafe5Q)s$#*vif*=>&N0MrG4%^ z-Z`P6FviX}rJ{(d9x09n|ja*KTbV(Vp5of)1(QdYYudX1>W4 z+HIp^jtnt;G{0%2dq^els1d2`eK!8?N(57L*@lKpw~zQ`rS2^Mb7&*>Ow-=P& z#5r8?VapHJ*Qd#luJ?T-mzLoitm-TkaSpR4h3`nrE5qmNEccfXUYP(tZbA)5;?x6g zoI~pPCi}eraSV+SZxowtU?ZsMAl=a9Z{O9G4Ue8`iRLVIerAt_WWMX;$BLDB_zV*fN~U;Q22G>|CPrOsQHGcFPWa z)V=b5VEwMYBLCBJ(pF(lCv7;=9LTM(!(h?2J`r?Q4LtV(9z|an7>cj`cbnin3wY3& z@DAEDLLRUf!L0Lo-1y5ZgsO2rz@SWBaN_ z-N&j*liP$Lw1H#EUKv|Uud)+BSvy&OT$Ajx!lo8c91%Ld2@e-8ZtFZGBdBp!J222 zn398~m248xH*lBL5QUEA$+LRd0sj6#uwR$1lW}~wU>mMS_y*R8ZnQdkA+bW(L8}UT zwYj$L0%m7$!LFww+dl)dPcV93kTqxuA_rgGo4{0bYiggtUgy-YYktuB$BztI;H#VR zA|l(Z@a4{Vru88e%!A(9hS4itWc%(o8@;}hFI>sDOmIOY+(lZfYeT;V_A`e`9Y=91 zj%aB=5=`$nS+Y7xru&N>j34!~>z*pos?s}IMffj@fJ>RC;SVNeWuI?c& zuetMp#0E`8Lh~(-P-e9bfP!~!{bVF3&;Dm7+h3+Oxp)^`&q|dmX&|qMRA6D8b&76# zsQW#S4prO`yG+iTGY)1K@jP>6C02W5b*R!)rFA$i4|p(@BLocjc9%a*RkYnbwa;10 zukVkpW3a)HbI@mQ8-D~sY=*BXM6^PCKfmycE*I~bw-z9eERLa)3-xz!Y z?G`72tS^eJ!NA`L#E>QnqxCE-LUSLF32k;g2eoxB^d|6dRjf5+z)1!UN*6C)tR$55 za^e#Wv}mV>DxL1ZV76W1S=&(ZtYT;b--)O)s`+xIc<=Sh;BK3qnhvwE`C0>VcR8OW3<(C#JKhwz zAKnVtuH;S-s(q>y^k05p`ef1dZvCp?HxUC9jwsN=vI}k7VS22W+5rb9bR%sLSZwO3 zDt!A77JlKm?9^0$6;AJ@9-1cFU58!ThVsx{r7pJYbn2ffI%~V1vEIsZprbG5J^mT+f`C(RMddcQ0uApg@pJFQ0%z7dak1)AEaolm3-4kqIm+ zY6i0`+5{5D+ED}E-W%x!K#4AN|7%sAYrG-j#05FiofzsVffpy3H|}Pp-QaTIU-|Px z<(vnfVX<(({rAsLg;sm&9cQVnflv`$VfRG(SM`e=*0RpOMLk0s^FDxaUtJrZZtdRb zN*ze_JSwvGv9HLc&dZhYT9)CRXi3;`jvsyHh9AQ$_Gt_9P_daXa)}|g#EXK&GH6d} zlkIx9rtO#Do~j7&!LRXmbVE2zqke=`j1#Z*Cf$CFZTku_8zFfA?bNA00r%Nv2||-= ziT>~K81d5ACAPl(%J9nA940xd2MB#bWQTIU$2-;tay=Jh?B`vc?mfGFN}$1&`X^d zbJZ`wDov3wh3R}JQn31*fQfT;&?wHFmEczJfj^erST`P?B+~z2(V-R$CYGM^nC&?Y zFR6ip#r3Wc$H+Y(h&5zEc;)!Js$CAHT^sK(uOpdk@Y4TwjW7^({*6t8!&-l8ALu1m zlLfRUSr_OSm*B_C)BEX*gJ<&|^f$2ORBz07usznJ?Kjkc(ER!Bs!HdtQ^^M}#^O{W zG~!5BHjGCw_R_$HKQe&kH%~BPw$~gbV@Mk4hl8?G~qV0;GS9y{+G1LJ$G>(!(Ui%7+ zZ(b$-9yqYGbQvV3@a&+_8mZD#Noi?H%bDJ&!GRm2nOw-yeUtOt-~Xc8rvEXOyx)`BFBZ8$T^Mv-++Z<~b@tDSm44#`#teOYf-?$|7{t0fwHx-` z=J|Eo_GN!Y_RS-W;W;mo8yiO8h8ewlK~26l>~OP$YCZVyEj3-JSZG(E_<+=L3~b~~ zMJUarBT3wL#Uk@orTFpV;bB<;&eL>Go8C>iLz^~#mQ;y^PUVBaZFeB!6Fqx_+KZe# z>+bEp>Sw9m_3i;!2z4Y)S;!CVOSdb*7w6gZ2B8<)5_i|8Y6jbf|+I)2<`Anh*#-bxtM&$`Xkj8ja9b5$1BUo42t*AwV0Y7t?) zREo{SH;3Zd-`mV~J{1uz_#iA@?7&I_0>A-rX!C8e-Z`mX4kH^0t=7}^wEqDC0OZ>y z28fGixYQ8zf`vuzTQ;GROP8u47Rzq?Jt46#4at0*1#gv@tRi$|K#` z4!&+;ZZ73le00bW1{`P?wj49_cc#qamGeEGEG+Xs0EL7qmpJEdgE0?3HJvjSi2PKo zULS`EJNZ(a?RGPdh<|+J`0q0kDXm2|`{T)Y{^Q5XQmoC}2s5QU=Q+|R{!=-&NsC-`#XXo#}q~G^Y7?? zQ;=fG)?W}HENRuEvWY-6kux~}C{tO4uxT)NPC3zcc0NWvl8k%v`*5zHJyrt#{< zuczf-u&^{X=+>4~d|FrIkOqo+L5a4chPu)4$*V&b1M`tNfer0!-}ys`h&Fb(nSF-X z2dVQFw8tH6X^PE?9FIWxM)@HWW3vS-$3X2ocagF$GV0BY42)wDw}kXS?^>-^GQT8#Y#FnZP+f5s<)T@O3!0)0TrCVm#|E663f09=Ikq>}R1n z!+(23H0{r=AOiW7qDn19S{AoFMr-6x2IG7@eX6jKX&MF9cP=sTh>SpO07nEFO6|5D z5;@BMeEs(XWBDyZSndE;O?+5sZgpw0Bd70j9O z7SFRgmk6+nkD#>>Jxx?iYUU`x9}SjWI;W&G=+cY%H}(;SP?Y4x8wVw&uX%Oxr{?UR z_GHny<08f7jvrV4UFOfv=j=n%G6(n7t=GAl)To>dCBkpdeN)d6b{#TMWrQWp3S5LV zpyd|VURSzZG>1vo-``nS+OrHIyj)XsBA5M+sP@TCeB2b8dx<_^TRdYoDRQ(XQ-dW_nn0`H<2M1Wy!Fmjj=@IJ&-5ntE zmNSgM+teHEAH;#R!2pqDF4>W75>~ z<_dy0N=J?3^CaWEm!GoH4o6)ZcThM!{PziEZl4oA-d09@XWSKzrw3J!1WCQG&5L_& z=yd$}v)_jVnGW|!NG%uOTL0G3JN~{_DBds{jI2waRM6^FM8?L3#isI!scgo`Vu@Kb zOr_+i1hHD#2^lmS`8^rET~`OFl?yHpHZiN^3SyB-*=( zs*$a)+>NvM4o?~El?cbDy!K-Z3|27O4~K8m8aN0BR8prnXpDU+J^FDr3Jw*`wKN}K z*q&d=SY$7xZ(~Tv+Y0^8w|&v96Y2a=m-_lkVrrwne76uGEw35qdmL>ymDu_fUtK2cZk%E${dM<9>r4N1nl9n~ND>>lY+;~Y)u2_*(c&>x z+kG`%^3J+@{YG8^{vN(YYL|XWs~b;t>3BFBxqiu{?cv5qI#;~5-BoE%u0hA?uz6y{ zcz0iQBxW6+hu#)zb`9AVbL2*b+Lt>`i*IAhjKXZll0^%+78OY*l5&X~w!9oS3aHza6ftwk>h zL$n(e1qs~J0JS)2_#B%j=QR~*7dmn&-)^4eM12dEQqT?1Mt{D`*%HbS@vuL`?gEhf##lloIEV%%E} z*1NZcg|-A8&ebep(>C}Pi{aEZs1%%Smt#^`>x!XO7q>#^YV?CUy#N3^%A+K<|Hx#%KINuB=RPlU$R!W!2xrh{^6knA)@515xrL zVW#^i@MjWk#ouh42$_dm;{O^?Egk7O`;RJhY+2Q-;|aC*2TjpESL z9eR89iI7SSOkTEbgq~NSu*P8@qrmc8H_MJyxekS?+O^E|Hc{uB3Mc2oa^gARX`A~A zuqlm6GFCYAI{(zDnwtjk!i0XAy_eG|X(oQL8QsbLsag?6@${0U9Nqw_GiY3HUQ_(t zK~HhBF(HeOw)KS^;=A>SMV!+`B`=q%P)ytdT&%YBx~II^l(tw)=xiyaVN`Y!gsg31 z)AaM~6+0>Vpms(quiPe$7-}cuVrzU*UPVVTW?J_2eis4=NT89VV<4fM#m!F$dt&N%b&SzEgr;A4~L{zWk z_@}aURjfX140+h|U6Gn2ej;CJyh2p4MSgEYb@|%b1#L!_<}zM;RP{Z>{XC7;#)c&{)S#w=2>jAfwpF;~@D^30{f^ z{dthW?BAyJTeL-7D5hYZuL%i>J=R72m-(Acn;{}f2C!OewA(9f8zUjA5?_%@eXJdS z#T-utkmA3M_I0md)lno}@|B*V*8OIdnNotyFJaN&sp>ojLaSc%4sY^yy0%3;nmtLo;bhe|ahIkE zWUG(D0woDt?25s!MrYpMj47xJTW>MMvewMKqp7Sm=m>#6a2%J?`zk_rQb`QjWx1!U zCG;6HzIwpDV|tMu-c<&h-?7(6?kI~`Yba+0am`#xlTF6_LCjy96-fIBE+#b*hHHtc zfKN1ALfM?OG>g$hAPZKt7N+PV5IxjI^BGy}iZG6KumYOOs5e{KXo->&l$p2W3~(j1 zu5*)GudH{6U@I90T1Q$v$HmXV=utDlw*hE-FZSk4$ zhMsWa+M11^u)TaR0x97H!Bi#aXkHL+Pg z(>v4uft@y`$CQ=F4CWzWfXcxCDPcRUw^ZT5`A;tOO;g1D3xocx;R3CEdU2Q-@<8P& zv=q_Z@vy#?K=lj@SU&;-GA0$xL^;F!DS?1nXDAMOeKBKXx+j0D__+IeuLNtC8wS>U z{&S({NHS}R?p`Zl*8PmqxjrpCA=DY|m?dYh;oJq6!KCpNh%zhKS_a;82W;nvj1s`v z_B_SeBQeNwZS0)UPMkG0PwVMPf%lC z3k#X=MvQE>UD?7dQn%i+a9BT6gMPRheofPQi89VE0FdOSvI2d~P&HlC}SLaC&2_>Mt3ttW|nBn0qUC6zN5RPJTT|trxWRtG%)CVSc4) zywPw+D!%nrQvPsaSiSH-f1_1z@vYTyz8V5xC$Z1T{!^d2qQnl08MQJ!K500gVcIhS zXse-r=mUbVqo2b;(_S+<^4&jmUZTn#zsAiiWBN5gAJ@_q4i++?BR~B%W;vdCGKY*K zFG>+4zP}j>jS6dYZCz0gB<5G=3{(+kdUd@D^J{mg7M0EI+8;u_B1_{H`=uPThV`!= zuLK`6vt1o2E4IUNQ{H)vO^vQHEAXjtme}aMEvRfxbBc8G55(MwmxndkG+kTk%<$gF zqC-?IAyC@P4Z8~Rz~Fah`sDPp@|&3&-w0df1Fz&dpA{3ss|)O{QS}p@SQP+CNj;I5 ziWvK50b?Z6giYtXrQ!vr^3`I=xB^Yb81Jb*1S(bgFrVKh-WPC`0`nmRE|V0l{>k}% z>ibOcpY|@V!prD(0<>kC*VnG}I)G2sg~ob)JNVV@oD=G1@l#&LcC1fF%ReSnF%9|< zVp<)}G+BWzLBhSIw!S4HfDv=FpxHQ@W-hxl*C~Zt{UpV!0?t!n!fkBn%zN@zDI&y` zUa!+Zd73Px3f64fPV1S_b~#6x80oam(i%HE&Gd%dz=t|f=^2|tUmmI(2A^xlG#>eZ z(mf+o5-9XO7!tyTLpQJfaYET!WO+vWsPSgWF~^BxkJ+5xZ4>na`_Sv*Fx}*S&CZ&J z9q`N<3Y=~ITad_9AwiL-0GDeRnQ~+zbnR0~@8i~Dc+E0M7otC0GmuNQtJzZ=gK`MU zf%4Lj17|!^9+|a`q44NdoC$tpE5Yj&eRT?s+gaY3P<&NFq(JES-R>zdifz_qtcwhs z0%lU>tt9Nv<AXB+Aal?@mSV< z!|U3(rn;u7KaiaQb|1`3iX&)=dOos$da}Qh;mpE!KeM8qV3F3t5lsv~;v#(Pp2XR#JaRBPjC%(2E$nj)N~(<1p4hk8>Ru|i zrS{Uo^ilVfl?oo&jhVgO-ULA(iZSwA#RQBdd$QEBGK_4!SlSR!F|dz0fIMQ*!CXj1 zaVvS;n+l!p$Z*&~rYzlxnVp&(?8Zkhf1jic=6z{l(b^b(2uCA{O)V13eNSU`drCAJ z)2tv#{Cs!HQLgtuTK!#?Ho`gI7Gf5^ceFf}|NXpAO7wJt zjYHP_BEN)2dY++T#4U%0y><`<<3Rxx+lxbnD@H932M5AG*=iss<`3>zpV>4=ydXIM zK@mSL&tm0o@?f6Tp8?U+6pNEl6zf@e{Ya<&`CIvlDGOm4HjEVo7CvSJ2fYf4+&2QN z$6_j@F@y>JWQZQz@>mUI(KE4D+(#RQ=jz$*SGnAs7&-&*Y_@aV=Ay;`n&2>ngG@2xmRf4hl|*#~fRg z_jV$_iFtT5>AY3HiWJ@6$lH1I5V^6lwdz%-_-jnu61XB=sWlWSP3tr2c_Av}MqnA* zt`|4E?t+Mn5oC&0IeWzwozw*HL~`iHf>UuAAqJQR78W!Sw%2{bF$xVG`Jk+GAjpHl zF#?ef6t6_CU01r!9E+wf%dUE9iXB!h?hU02n7OrgngT_f9sYwZ3g%L$|}E-H1qUInyqtoeeGneqBEY)7e*`fMkI z;h59C?j4gULExf;c;xj9h&IHXj+=IU6Om&b5+*y?$PQ(_sPfHnY?(y6xo;ik$(14G zy9#ljk_n9KiQ@vR^NcK7&g40#mNi`^rK7G*EUF3X8+*N@MBLIFkDXw;%t?@4-DLaJ zlquz-I$MXO8daWneLd7_3G2)?Z(baOG(|c)&Jd3C&BYV-5-7zZ$U;?(-fP`;uHoY~+zi_KeKIS4*dz z<~0TS#g>Z79BLnasr~BznlLzu`6L70hCH>*g>iu1_J++v!)XgE)%no8$rO%yb*_5Tc~WZiOMSZH|^vNH9S z{FUS?cL1qPwUhXLDe4uXYcuU9`m6Nj?VAVUPix0t4xiX^Rw6rg?7-CsdV8GjXl3`N z7&BUz*x|%gSC(L^9GiT+Bv82Ol%VlJ?GN$?^=>(-K_re%s$yWFmUZ*?g+NRJ;DZ|w z?z|E|e;FZN@PZz2y7#s1r0mvz>}W!lbN3qfsx~5HVa$o121oWdRV6(xllKkJQ~&ft z;LRxPG5H(%Y`q%`EfB98mhcRxNLgSq+V8Z5g;ue$=oF0*t1HeTg#*_2eg1t#h^ZA0 zT$Jv2{ua&KGbn*VD3B8T3NFSl`pdHJ&wmT*<#3H?NJ<}1e>4d`H!IpTC}an&dw{Cm z`kBa!aKPILTVZg1No!#=J_U_iHC~vNZfe>(Tj9R2F%Qy##ta&Rw`}fvlT)_;q==EK zxno2`&I@?=d{>J65f&C=9EJbv?N@q?u@46Upjn?iU>eVhAPUa-XJSms|0SbdW)Yu*6H#!3s_1XM`lP{WPOBbI6Gum z$h|wt0sd>yh4{ulbg7j=g%+YAerrOtZ|(`6$(@3Y*!^3b3(4pJiV&b1$x2e{ zCC4+2?XUW}fFC!~UEQSlIi~4;Lccgu@G^U@=6#2zK&rYj3Wq^pOyB>Dt`+FR(CSA2 z^mC`2j$KmH`O}Fi7mPf&_nKtRzzwnJ>)_REY%bS;QqAOo-Pmo^`s6%sfP&!e$5Wn~ zIM9o{&fh+zX`cK}sugE)5^0Q$hsaJIU{GYmRAZZ6Hp^0aN`qIj@h^u_*rxNO5gW_v z%yX|vFaWU?`9XH-X+10pi=KuwRyiI;qtc#6Zv16EI=2OV!F{NM z;?8joIw=vguM}(TTXIq()MI(gbPL?Tx^3Bz?K_w47WM{KZFaxj`WXdx95o(*!;lEj z?S7o`HimQZTSc+QJ;(7Miu>Jg08fXvyaT7rKYTDw=TS%&`P{oW`V^Koy>j$%HW0Qr z41p!3>(#7ocCEe3fXrQ>nuwr4sT(b8`XiQI2DWNm>ga~QzuU|_JrIR3E2&!GEIBp? zhTdHZ&>K#(*gPOux!}<~QxD+eZ$aij49#2K!cq=Qo#gG?gstl$j4&r6Z;HX-54ZV{ zC1>BBxL=iXjCOkj&|7wb)Pw1sAh7EB32&ckeNBExRcDf zQPsvP?PALX6g>5-RRckbP2{xc6~c;x1&Rniq>2fY9sL-0gQE zW^Tingk%gwj=HT|!CkB?&7*Vf`hCVAk?f37fiSaOJkS2m3IK=2s=k01@YST6=3KEp zwfoU2|k4s!s+1uT6W@FU|7TY0eTGonC6(0;S=Foyl0H;}oSo=_NbJrM+ z%j<3^QI!}&$vS0RCViaECGO2Mbxauf_0>+;6;fqz_X;}!LK;Z*JN3M4?x#Z@qO5oo ziaQmWU3q=O&7d+x$bDhd-~X`Nw^xUKroKWVBSCAtIhr+Ce!)^nX$ErL0ScRHtFzZ$ zQb5C+){aA1k1*5tN9S6FEET`vqn&Y~$eXtO5(r5J2!_@y#m}VChKXEtLsIXl>&ynG zc;C04cgZ9!=TjwF@0i3&ddI6GGi&Eox(wJV7Je~ccK$6jID*&|;7QJA^W+dVy>unU za^~Pav8UXFZfpIl!xV|lLo7NXkHwiz0oL$dxY5UG>S;F{jRMg%klh&BMT|MhAyb^Q zyaqpo)WM`jlV`=#!VioWD=jl;)qH3P9rEzJgD!-!5tOUFeKvQrk~!3~qY7)OItXDK z2+PG%=S*5pQeVn$bd6Ul@Vt_b^enAfYM7qyBYVg470E$d6q!0DrEZM9;a}U6+NT}X z!Et`!ZyI?I<%nJ}q10>EM+wb!DtB(wVn>DKy}q}gzf!?16n6IlowSJ8NqE{1t0MFR z=Wc0=yQ2~(-h062DWys15wRHzf%idGhkT?V#S&aFJs5|15zG79W4{I)>%X&QLgq82 zuwp>>ZX1mXRwu8PpTY>UJ*JY~oI z^2s%|5eV+8fHLH6HJd`Yh>=g8*(FVauk-=Al~ZcDq@W4L_fW&{Xi!QBK%z~DP$1ZR zEqzpl`l9@SuEq;NP}Bgb>lelutj1-5bfZHJYHo86o;lUm zVtXZ_y^A?P%qb2!b|&wtLda+9>;KNClpR~W4shG%>8NS@fJT98@ZX?hHsqh;*DW8# zq&Da!l=6;Yp>mkP_QJob2>#z%&KoPu&u@4Hs=J6-_O>%wP=D2F1stp+VXTX zIlJgE)DQ_eTXt@hLqW^P=2m%E1{{vrj&&v9D7|-QVX(86&J*XoDTu1oOy)K*cggZt zwwb3pZ)oSq59!aHZ}K)fUx6x(a^O6B892!_l5Ag$ZY<}VdIxUo0VTNS8c~~}ei8jB zJzmJ7CB|(nEhR&a4&`m3pVCl)#&#;{AgZxKHA&iaE~~TRg@?~J^lp_REetKVQ79MZ z=l@4}*BRAhwyyCyqoboTDALP_1bRVP`LOE8&#fMn(I?@zch0%dZtqi zfP3Z@eJ1YZ#t7Nv-$}2qWcLH=syckt4G>7;^vzL8@=^W96vfYPwJYNUmL>N&dn5of z1_;rnn!We*d=3PaK$-n*U`h_dzVLudc|THIcJE}u*&aaH+}rjXU}PW$h;T*R4A|k& z=3NQ(c!)Dd?9oI7{FS4%H|H+g2omr~c>s|^(8%yWis~SSZ znQqhD1G@=~k3>gs()ZMgKL-)7~126EbH4= z@_7~CCUlz$KLAIMfGcNZ;&Iujd>*&ym;BTuvVh05cXwB~ckkW;Afhc@{9FLW z{kHhQy;dC~JgX`)Xnc`WV{W!bD_=<|OMa&qK+-<%0t`!C)YgN~0ObNeB$eGtX)eda zerYqij^_-$5S^<{J#Pwx7W2$J)yJ?mJOXcr)A}`pI6UTcXIuHay$%V)Z2+su0<6ok z-w|TBjP~f|wk}8!OaoLoL3*0j-rlWkIRNhwf7^xjaj+;IB^4?7Y#sLY-fb>bJ8}zZi~kvh zd=bHL0@ulk{)gp+!WSv{LI8T=)~Jer&}va8INsg~#3doTKArFh1J9*)iI6btl$^~` z$FYpzsxVqvt7=Opi0ET#ijy@ln9O6@pFVw)soHbA(DZzv=|rNw*){zeia^w{RbWrM zWdBM1BX$!&OQghlH`?_Z%8E`$0A%|pvs2;gj^uH^o?Q^NnH!ln@t4;W zw`1swS2xhhzf@fbU0Yc3Tj(j?*TBX_hdv-rJ?An2f>y`fR>)cbJ9Mt`OI(t9;%M@R zRO9PLt2AjrWdFOaD(g&JK7$rlwqRTg3Zo#G!-VifE7GlFN|TJ~E&899pL}K=FMVq24|nS+Yt^G6+eIraYr3?Juq>1*vWeE zjK?dTc^;IwjrI9_XM(p7pyT(mTaeI9zsOba{8=k9SBO}(9 zimdc1ao@9s{VBTOD+#u_B0ozYuURH&smmkr)RbBhIs+co z0I!NHc$t_!A6Y-P4&HZQj1twY+h~T~H67OG(TQXUUNwneQ(ZV12@`tnomnIfqpprJ zb|-EtB*^J&9?y)E%5>-Ovgv|xpHmHpO^MzDiQxIK_8ZW!^Y184#fy@Sa6wCSagd3( z978f^pci!tzS~Q&5#2|vEmv03?PAOgRqi8;{_iqj#{&*uR1M}G!F`#UJyg3kHDF&& zdx_+Fn|zF!nd2F$pEnT_t0NPE?Wi^r;`Ckm_~Qgz-)ELbf`Paxd^q=;M!FA4{8NaV z*oKP>meZ%jbJ`#1It?jj@g3pd@-@F_?@CCqNqHP%x8`oZ154i%xK=W+beXp`FH*X%l9#E8_ zt#*d>eRvQ#&gQV6+pzIUpN3#LW_dO4B{|%;R-LPc*m39#os)O6j_HJl1MI9d5i@yT z8K4%E^Pm-W=G27$1i;QjiV+L4>m$mB7;X~kuZljwU)^u=GM`RP=~}>@fuwZf#}VO( zD8@K~O4x}Oe$YhPo@Zi0AHWwHQ&)*Kj6?)&T^gyxt<8@sHjH;`Zyjx-@)sxcxv@<_ zx|U}3Ed{nV-hqO#Y$h0Kz^{_%dTMQaYc~w96vD`|#Et;sSDc|8WC(f} z+|VTv0WkD~-;Q+V%<}}CM-bsW!@-z()np%&e6Abi=pqG-#|3Ggv|9v-40vt+CX(Xfd&)D)nInepl9-LxuiFJ2NIx^g8mPk#_xqc4 zBFt>ji@xMcakc&X@dz)kq=aRUk-)uq&Smaxy(ucA`DBmR4>-IY+_ zh*UVAA}NQ-ypM~adbL`jb;zO@yvfZ!r0P9{Z9*_h16nbL;q|+E-G?xQ zI=Fa(Unhj~#ywkgDen1#EVgjWK@*BOS(7at+r1gC%`4P7t?a*cmhSsdcj1%yMX34QUyY#4Z=3LWj|Z~kw@|rYvmjA zp0RdkXkcfwKv`g1jv5aMA!iwqYfGNI<;!23ZkEyNrJR{R0rLwJ`@)LqUpv)KuCouo zAl`KH)U_@0Vu`%MP3T@zTh5^JpBaJXR6R14(|qg`zyNAh+G1MlT%4 z5VQYhN$7to4)0|mP8^KEIi#dO`k%sF5|Vyba#wFce;o#XbXwM1VBC}`@b8(<#dN#zAIk{LB6h1kEVFJXS>aG8w2T(l+M?&{FyjTMY_B8t zW#!>Ez3}sHF?6-GI8YG)EmlPu*Y(GaGu8FBmBZ3vPVYilHk51nkUZT(!-BFtZNK2R zwmfoA&veO_HRrL511bn9=8{F6m>33kCnSeX0)3afYC{pc+Y56?fW=svnZYo-qoEd$ zpgVisUruskuXR8n%tq^nQw~#dlCp-JdFI?OrGdmgMx?t8t03EPZlDM!ROm>skb|U1 zAV@UDE#tjwJcKy*pFL1`J%Aj$`wooMMC^sgoafX#yHk%T_;lU~#?vtI6aawtdb7Z6 zI|jXtiaXB`@ zvUV{tIa1~lg#kqUyh$J5i71E6HtcA0%W^d<>S5Ld6q7*8Z~+ass0lyN%(1;A1d0X_eJ9eHmVK1eJawj~L%kP)3AG)Vl>k%{re%%HN*#H85^*W;kL_9%+1QU|~w`Q>t zKl(uB3}gjC0}hjGUGsBnPM-nuk;7hObd?`gQuZ$B%G}9(93s^q(ljY+ki)MinK(%qiX-JQMVdCWW|Y^o`KwJG)_( z@et4u`_E%waewcfnL<<16v7!^I*QxiU85N@%G4jJb=xI#qnu%Tu3qP(M~`l|QG`_k zx1}rP>C%jitPl>brkporRbXybKT{A3slpT^etkA~2Dk*<#l%ocWXHhJh$FuidHl#5 z0eJJ%$<=JORA+PBQ&li{YqVJcsuh4_^X7%_r<^&!Qq6@09{*jC<+)cY02kVl$6>Wl z$H85{@mW8}II3)cOmahgPouKr-t%?rHd1Y;A-DEgl+e%jU4RJYnM5e(7t01Tg+bJ( zjo&>jtsf;_&-1abIV=>ay0NrYYIketXbB|(j1ct5Jbe($MgJ5!>6filQ;`+D7&4V> zPM?h^od*|41IaD;8|v6gy?3Ww-l$%ZsIY!PRW7hCCEi_$k#xKDBZFME{Cj`RDf{i; zA|XiTyT!5Tgf?sn{xEx^x#!TEM=($bjLWuNMY5kPQ?*Bnk$Q$6dyI5H-95WOXm00)5q~l=U)GOr}vvFn1u_|FCB#81hiQQNsw1Seh2{6V>@yA z{%_}}^T`q_8JWmq&I3X-3Z`ATeB_`Om)45oFx>X(;VNr6or{iJzy#bK3H;>DmnB`A zTr_uVSEamR7THEp!sw~Vm2sh~ik=X=h}l;da^uyul`LQ+GY=FkFZK}?3m{B%Rh(VT z)hvDQZ?agU%jcJQw2me~(jXa%`*xXLtFQm5(S4mx<}=yCqhnhSy+NdrgOEIG`N|KVpc2>v*aW9 zN!UV2Zu-s2M$ohPk#nNw={@>S7B~9F zjJ18Z1vyynEnqxJmE^b&rD)jN-||rk0LVgaO!`K^U7=zS{zIvF2$z>VY|lcm8#l;! zx4*@jwHjE+4r0R;^S1_3GzOp0E$<4Xg8U-%>7Qz)XwVHTZWH60e0wShEYCMpX4s)r z-)hhBRYGp5PI(Q)ZcitxWo6$;io|E2IzfRM$igBo-HIZWzU3|o9bCVtdn{a2m^F!a zKK0#-FYe8BzU-kRx}at@@KUZ3$w1w{Vq$8#VcPW^cdN9BTMaSK1@05`=_&5eEe~7V zF5}^s6!Q;0I3aw>W8C(*B%R;Uqd~2jpjB26Hc3CT8OLo8O_GS9OLQ8V^w5HV9sU^R z%cBA0&O+!>IS7j^h-rkzrB)pi44(O~%!deyg=&24Lm~6WtU}+2lz^Qul~=o#kH=5< zhi1wQMa~XClKxy+ONSW3U_sXo{zgast(5law08gwq;>1+7D$y9RP(OQzNxYtG{4A#XZNJT$8>Ky@O=|LS(Ei(lxjL%+| zwPovR?X%036BAo6Dz}|#mjn4bVSeZC=s%+DBfz8Z_&=&kg4V``$G?=c5`OdFp~#wl zzh6O4S`)LD*B6UmTmWcuI_*w`(h4HJ5uc47*;>P>4*0-a(eQR zl5e4&^0>9LbB(W|MG}sU%=i2`+)pa1yrUn&AW@!govFIQkT_EO=cR48ZG`8q)dkx<n46$$OL)*+x`vz4)YCl&;PHQhCJN5T6H~}*I{VAcyGA*>G1R4hkNOJ zUi5+w5lwYXt%K@^;m1)^LtjHn|B$+hy1Kr)`p6k$zyH!8DCE4Kcg#O;P$F`z7aHvU i+a1FFg1o}QzYn_b&)aZ!76><1w=zFr_VAmtm;VzKimLtq From 7cdc73b6b9f89643c2085c26b0ad459bdd102d3f Mon Sep 17 00:00:00 2001 From: Ciara Stacke Date: Wed, 30 Aug 2023 10:40:08 +0100 Subject: [PATCH 5/5] Separate validating types & review feedback --- cmd/gateway/commands.go | 70 ++------------- cmd/gateway/commands_test.go | 39 +++++++++ cmd/gateway/validating_types.go | 86 +++++++++++++++++++ docs/architecture.md | 2 +- internal/mode/static/nginx/runtime/manager.go | 1 + .../state/graph/gateway_listener_test.go | 2 +- 6 files changed, 137 insertions(+), 63 deletions(-) create mode 100644 cmd/gateway/validating_types.go diff --git a/cmd/gateway/commands.go b/cmd/gateway/commands.go index 29a5d78e62..498780db14 100644 --- a/cmd/gateway/commands.go +++ b/cmd/gateway/commands.go @@ -39,68 +39,20 @@ var ( } // Backing values for static subcommand cli flags. - updateGCStatus bool - disableMetrics bool - metricsListenPort int - metricsSecure bool + updateGCStatus bool + disableMetrics bool + metricsSecure bool + metricsListenPort = intValidatingValue{ + validator: validatePort, + value: 9113, + } gateway = namespacedNameValue{} configName = stringValidatingValue{ validator: validateResourceName, } ) -// stringValidatingValue is a string flag value with custom validation logic. -// it implements the pflag.Value interface. -type stringValidatingValue struct { - validator func(v string) error - value string -} - -func (v *stringValidatingValue) String() string { - return v.value -} - -func (v *stringValidatingValue) Set(param string) error { - if err := v.validator(param); err != nil { - return err - } - v.value = param - return nil -} - -func (v *stringValidatingValue) Type() string { - return "string" -} - -// namespacedNameValue is a string flag value that represents a namespaced name. -// it implements the pflag.Value interface. -type namespacedNameValue struct { - value types.NamespacedName -} - -func (v *namespacedNameValue) String() string { - if (v.value == types.NamespacedName{}) { - // if we don't do that, the default value in the help message will be printed as "/" - return "" - } - return v.value.String() -} - -func (v *namespacedNameValue) Set(param string) error { - nsname, err := parseNamespacedResourceName(param) - if err != nil { - return err - } - - v.value = nsname - return nil -} - -func (v *namespacedNameValue) Type() string { - return "string" -} - func createRootCommand() *cobra.Command { rootCmd := &cobra.Command{ Use: "gateway", @@ -158,11 +110,8 @@ func createStaticModeCommand() *cobra.Command { metricsConfig := config.MetricsConfig{} if !disableMetrics { - if err := validatePort(metricsListenPort); err != nil { - return fmt.Errorf("error validating metrics listen port: %w", err) - } metricsConfig.Enabled = true - metricsConfig.Port = metricsListenPort + metricsConfig.Port = metricsListenPort.value metricsConfig.Secure = metricsSecure } @@ -219,10 +168,9 @@ func createStaticModeCommand() *cobra.Command { "Disable exposing metrics in the Prometheus format.", ) - cmd.Flags().IntVar( + cmd.Flags().Var( &metricsListenPort, "metrics-port", - 9113, "Set the port where the metrics are exposed. Format: [1023 - 65535]", ) diff --git a/cmd/gateway/commands_test.go b/cmd/gateway/commands_test.go index 59c9bd7bbc..0c352fda79 100644 --- a/cmd/gateway/commands_test.go +++ b/cmd/gateway/commands_test.go @@ -118,6 +118,9 @@ func TestStaticModeCmdFlagValidation(t *testing.T) { "--gateway=nginx-gateway/nginx", "--config=nginx-gateway-config", "--update-gatewayclass-status=true", + "--metrics-port=9114", + "--metrics-disable", + "--metrics-secure-serving", }, wantErr: false, }, @@ -175,6 +178,42 @@ func TestStaticModeCmdFlagValidation(t *testing.T) { wantErr: true, expectedErrPrefix: `invalid argument "invalid" for "--update-gatewayclass-status" flag: strconv.ParseBool`, }, + { + name: "metrics-port is invalid type", + args: []string{ + "--metrics-port=invalid", // not an int + }, + wantErr: true, + expectedErrPrefix: `invalid argument "invalid" for "--metrics-port" flag: failed to parse int value:` + + ` strconv.ParseInt: parsing "invalid": invalid syntax`, + }, + { + name: "metrics-port is outside of range", + args: []string{ + "--metrics-port=999", // outside of range + }, + wantErr: true, + expectedErrPrefix: `invalid argument "999" for "--metrics-port" flag:` + + ` port outside of valid port range [1024 - 65535]: 999`, + }, + { + name: "metrics-disable is not a bool", + args: []string{ + "--metrics-disable=999", // not a bool + }, + wantErr: true, + expectedErrPrefix: `invalid argument "999" for "--metrics-disable" flag: strconv.ParseBool:` + + ` parsing "999": invalid syntax`, + }, + { + name: "metrics-secure-serving is not a bool", + args: []string{ + "--metrics-secure-serving=999", // not a bool + }, + wantErr: true, + expectedErrPrefix: `invalid argument "999" for "--metrics-secure-serving" flag: strconv.ParseBool:` + + ` parsing "999": invalid syntax`, + }, } for _, test := range tests { diff --git a/cmd/gateway/validating_types.go b/cmd/gateway/validating_types.go new file mode 100644 index 0000000000..42d24782cb --- /dev/null +++ b/cmd/gateway/validating_types.go @@ -0,0 +1,86 @@ +package main + +import ( + "fmt" + "strconv" + + "k8s.io/apimachinery/pkg/types" +) + +// stringValidatingValue is a string flag value with custom validation logic. +// it implements the pflag.Value interface. +type stringValidatingValue struct { + validator func(v string) error + value string +} + +func (v *stringValidatingValue) String() string { + return v.value +} + +func (v *stringValidatingValue) Set(param string) error { + if err := v.validator(param); err != nil { + return err + } + v.value = param + return nil +} + +func (v *stringValidatingValue) Type() string { + return "string" +} + +type intValidatingValue struct { + validator func(v int) error + value int +} + +func (v *intValidatingValue) String() string { + return strconv.Itoa(v.value) +} + +func (v *intValidatingValue) Set(param string) error { + intVal, err := strconv.ParseInt(param, 10, 32) + if err != nil { + return fmt.Errorf("failed to parse int value: %w", err) + } + + if err := v.validator(int(intVal)); err != nil { + return err + } + + v.value = int(intVal) + return nil +} + +func (v *intValidatingValue) Type() string { + return "int" +} + +// namespacedNameValue is a string flag value that represents a namespaced name. +// it implements the pflag.Value interface. +type namespacedNameValue struct { + value types.NamespacedName +} + +func (v *namespacedNameValue) String() string { + if (v.value == types.NamespacedName{}) { + // if we don't do that, the default value in the help message will be printed as "/" + return "" + } + return v.value.String() +} + +func (v *namespacedNameValue) Set(param string) error { + nsname, err := parseNamespacedResourceName(param) + if err != nil { + return err + } + + v.value = nsname + return nil +} + +func (v *namespacedNameValue) Type() string { + return "string" +} diff --git a/docs/architecture.md b/docs/architecture.md index 8164d25e66..3eabd49f65 100644 --- a/docs/architecture.md +++ b/docs/architecture.md @@ -96,7 +96,7 @@ parentheses. To enhance readability, the suffix "process" has been omitted from 1. (HTTPS) *NKG* reads the *Kubernetes API* to get the latest versions of the resources in the cluster and writes to the API to update the handled resources' statuses and emit events. -2. (HTTP) *Prometheus* fetches the `controller-runtime` and NGINX metrics via an HTTP endpoint that *NKG* exposes. +2. (HTTP, HTTPS) *Prometheus* fetches the `controller-runtime` and NGINX metrics via an HTTP endpoint that *NKG* exposes. The default is :9113/metrics. Note: Prometheus is not required by NKG, the endpoint can be turned off. 3. (File I/O) - Write: *NKG* generates NGINX *configuration* based on the cluster resources and writes them as `.conf` files to the diff --git a/internal/mode/static/nginx/runtime/manager.go b/internal/mode/static/nginx/runtime/manager.go index 7e8768ea73..8280d3acd8 100644 --- a/internal/mode/static/nginx/runtime/manager.go +++ b/internal/mode/static/nginx/runtime/manager.go @@ -70,6 +70,7 @@ func (m *ManagerImpl) Reload(ctx context.Context) error { return nil } +// EnsureNginxRunning ensures NGINX is running by locating the main process. func EnsureNginxRunning(ctx context.Context) error { if _, err := findMainProcess(ctx, os.Stat, os.ReadFile, pidFileTimeout); err != nil { return fmt.Errorf("failed to find NGINX main process: %w", err) diff --git a/internal/mode/static/state/graph/gateway_listener_test.go b/internal/mode/static/state/graph/gateway_listener_test.go index 9b3073f4fb..f2c1e3bba2 100644 --- a/internal/mode/static/state/graph/gateway_listener_test.go +++ b/internal/mode/static/state/graph/gateway_listener_test.go @@ -114,7 +114,7 @@ func TestValidateHTTPSListener(t *testing.T) { l: v1beta1.Listener{ Port: 9113, TLS: &v1beta1.GatewayTLSConfig{ - Mode: helpers.GetTLSModePointer(v1beta1.TLSModeTerminate), + Mode: helpers.GetPointer(v1beta1.TLSModeTerminate), CertificateRefs: []v1beta1.SecretObjectReference{validSecretRef}, }, },